Saturday, July 24, 2010

Python and Google App Engine

Quite from some time I was getting bored of working with .Net and for some recreational work I decided to start learning Python and google app engine (On Windows) .
After installing Google AppEngine for Python and Google data service,I was ready to dive in. Google app engine works on CGI standards. I decided to implement a feedback form and send mail to users informing them about other resources. I started with creating a working directory for my application.
Google app engine applications contains a configuration file (app.yaml) that tells about the runtime to use (in my case python) and the handlers that will redirect and process the request .


//////////////////////////////////
application: Feedback
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
script: feedback.py
/////////////////////////////////


In above app.yaml file url: section in handlers specify that request to the url /.* should be handled by the feedback.py python script file.

Google App engine web framework defines many modules that helps us to write handlers and processors for web requests.
Google Web application typically contains multiple classes that processes the request and generates the responses. WSGIApplication class instance is responsible for routing incoming request for a particular URL to one of the handler classes.Finally there is main method to start the application.


import cgi
from google.appengine.api import users
from google.appengine.api import mail
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write("""
<html>
<Body>
<form method="post" action="/submit">
Name:</br> <input type="Text" name='name' width="100" />
</p>
Address:</br> <input type="Text" name='address' width="100" />
</p>
Email: </br><input type="Text" name='email' width="100" />
</p>
FeedBack:
</p>
<textArea name="name" rows="4" cols="60"></textarea>
</p>
<input type="submit" value="Submit"/>
</form>
</body>
</html>""")


class FeedBack(webapp.RequestHandler):
def post(self):
self.response.out.write('<html><body>Thanks for your feed back.')
self.response.out.write(cgi.escape(self.request.get('name')))
self.response.out.write('
<p>Email has been sent to you containing
futher resources.Thanks.
</body></html>
')
mail.send_mail(sender="Example.com Support <support@example.com>",
to=cgi.escape(self.request.get('email')),
subject="Your account has been approved",
body="""
Hello : ' + cgi.escape(self.request.get('name'))
+ ' </p>You can access the following resources .
<a href="" >Res1</a>
""")



application = webapp.WSGIApplication(
[('/', MainPage),
('/submit', FeedBack)],
debug=True)

def main():
run_wsgi_app(application)

if __name__ == "__main__":
main()


.
Above feedback (FeedBack.py) implementation contains two handlers classes (MainPage and FeedBack) inheriting the webapp.Requesthandler class. These classes implement the post and get method that handles the incoming requests. Self.request and Self.response are the objects that are used to get the request parameters and generate the response. Apart from the handlers classes, WSGIApplication instance is created that specifies the URL's mapped to the handler classes, debug=True specify to print the error info on page if any. Then there is main method that runs the application.

As configured in the app.yaml , the request at base Url initiate the feedBack.py, which then routes the request to the handler class , based on WSGIApplication mapping. Main handler displays the feedback form with post method and action equal to "/submit" url. On submitting the MainPage form , url is redirected to "/submit" url , which as defined in the WSGIApplication, routes the request to feedBack handler class. Feedback handler class creates the response and sends a mail to user.

To run the application we can use command line or Google App engine launcher.
Start the Google App engine Launcher and use add application option to add the working directory.Google App engine launcher provides a simple UI to run the application.

Google data services contains various modules that can be used to access and use various google services such as youtube , picasa , facebook etc. Routing mechanism is somewhat same as Asp.net MVC. What I found is that Google app engine development is tightly integrated with other google services and exposes rich api to interact with other google services.

Google App Engine


Python

Wednesday, July 7, 2010

Silverlight Video Streaming

Recently I was on as project , that involved playing the media files from the storage server in the browser. Silverlight was chosen to play the media files. Plan was to have a datagrid that shows media files filtered on the basis of date. After the user chooses the file , the file is fetched from the storage and played in the media element . Starting was the creation of the project structure , a silverlight application with asp.net project to host the silverlight application. In the silverlight application, a usercontrol with media element embedded is created.





















<mediaelement name="media" mediafailed="MediaElement_MediaFailed" autoplay="True">

Media Element has the property source and a method SetSource that set's the media file to be played in the media element. Source property takes the Uri of the media file and the SetSource method takes stream to be played in the media element. Setting the Source property was not a choice as the media files resided on the other server . Silverlight media element Source proerty do not support file:// or UNC path to set media files , files have to be on the webserver hosting the web app. So the solution to get the media files from the storage server and stream them to the silverlight client was to use WCF media streaming. At the silverlight client we use SetSource method of media element to provide the media stream.
WCF service will be hosted along side the web project on IIS . WCF service for silverlight application are little bit different from the normal WCF applications. WCF service has to be silverlight enabled. To create the silverlight enabled service goto :- Add New Item --> Silverlight --> Silverlight enabled WCF service , this will create a svc service file with default structure . We will start with creating a service contract interface IVideoService , having a method GetVideoFile that takes a string as parameter and returns the stream object. Method is decorated with the OperationContract and WebGet attribute.
.

[ServiceContract]
public interface IVideoService
{
[OperationContract]
[WebGet(UriTemplate = "media/{name}")]
Stream GetVideo(String name);
}


.
Now we create the implementation of the service contract by creating a class VideoService that implements the service contract . In silverlight enabled WCF service , we have attribute AspNetCompatibilityRequirements
on the service class. Service class implements the GetVideoFile method that takes as parameter the path of video (UNC or File://) and returns the filestream .


[AspNetCompatibilityRequirements
(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class VideoService : IVideoService
{
public Stream GetVideo(String name)
{
if(File.Exists(name))
{
return File.OpenRead(name);
}
return null;
}
}


.
Now our service class is in place, we create the WCF configuration for wcf streaming.We use basicHttpBinding with transferMode set to streamed , we also increase the maxReceivedMessageSize .With the service hosted on web app the endpoint address is always relative to the web address (Example : http://localhost:2310/Default.aspx --> http://localhost:2310/myservice.svc).






















At the silverlight client we add service reference to our WCF service and use proxy to get the media file and play it with media element.

VideoStreaming.VideoServiceClient client = new VideoStreaming.VideoServiceClient();
client.GetVideoCompleted += new EventHandler(client_GetVideoCompleted);
client.GetVideoAsync(@"\\Storage-pc\Files1\Encoded\myvideo.asf");


















We also have to create a clientaccesspolicy file and place it with service (.svc) file for making service available across appdomain boundries.











Now we are all set to stream the media file.

Network Security Access Restrictions in Silverlight
Making a Service Available Across Domain Boundaries
WCF Streaming Message Transfer