Monday, March 30, 2009

Making a Silverlight app getting data from Google app Engine


Recently I am interested in Silverlight2 and Google App Engine.
So I've made a simple Silvelight2 app getting data from a mod on Google App Engine.

I adopted REST Protocol in communication between Silverlight2 and App Engine.

Here is the Server-Side code written in Python,about which you don't have any other choice.


#!-*- coding:utf-8 -*-
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.headers['Content-Type'] = 'text/xml'
self.response.out.write('<?xml version="1.0" encoding="UTF-8" ?>')
self.response.out.write('<Person>')
self.response.out.write('<LastName>Jackson</LastName>')
self.response.out.write('<FirstName>Michael</FirstName>')
self.response.out.write('</Person>')

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

def main():
run_wsgi_app(application)

if __name__ == "__main__":
main()

The code above simply returns XML format string.

XML Format:


<?xml version="1.0" encoding="UTF-8" ?>
<Person>
<LastName>Jackson</LastName>
<FirstName>Michael</FirstName>
</Person>
Next is the Client-Side code.

Silverlight2 has XML Serialize API. With it you can Deserialize XML String to a C# Class insntance.

So I defined Person class in first that corresponds to the XML format.

Person.cs:

public class Person
{
public String LastName { get; set; }
public String FirstName { get; set; }
}
The following code makes an Asynchronous http request.
WebRequest class in Silverlight doesn't have GetResponse() which is synchronous version of BeginGetResponse() existing in .NET Framework.


private String _svrUrl = "http://localhost:8080/";

private void OnLoaded(Object sender, RoutedEventArgs e)
{
try
{
WebRequest req = WebRequest.Create(new Uri(_svrUrl));
req.Method = "GET";

req.BeginGetResponse(new AsyncCallback(GetResponseCallback), req);
}
catch { }
}
The callback method is called when the server return a response,
then I start reading data from the response stream asynchronously using ThreadPool class.


private void GetResponseCallback(IAsyncResult ar)
{
try
{
WebRequest req = ar.AsyncState as WebRequest;
WebResponse res = req.EndGetResponse(ar);

Stream stream = res.GetResponseStream();

ThreadPool.QueueUserWorkItem(new WaitCallback(ReadContents), stream);
}
catch { }
}
In the last part,we deserialize the person class instance from the XML Stirng read from stream.

Be sure to use Dispather accessing to a control in a code block executed by a diffrent thread.


private void ReadContents(Object stream)
{
Person person = null;

using (StreamReader reader = new StreamReader(stream as Stream))
{
XmlSerializer serializer = new XmlSerializer(typeof(Person));

person = serializer.Deserialize(reader) as Person;

}

Dispatcher.BeginInvoke(
() => {
_lastName.Text = person.LastName;
_firstName.Text = person.FirstName;
}
);
}

No comments:

Post a Comment