Advertisement

Making use of your JSON data in Silverlight

Wait! Don’t throw out your JSON services!

The Situation

You’ve made an investment in exposing some services for client script consumption.  Most likely if you did it in the past 2 years, that involved exposing your data as JSON formatted objects.

What is JSON?
It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects)

Perhaps a search service returns a list of people formatted using your custom “Person” object and you’ve been using this in your AJAX applications for a while now.  Maybe your JSON data looks something like this:

[{"City":"Queen Creek","FirstName":"Tim","LastName":"Heuer",
"Website":"http:\/\/timheuer.com\/blog\/"},
{"City":"Portland","FirstName":"Scott","LastName":"Hanselman",
"Website":"http:\/\/hanselman.com\/blog\/"},
{"City":"Redmond","FirstName":"Scott","LastName":"Guthrie",
"Website":"http:\/\/weblogs.asp.net\/scottgu"},
{"City":"New Hampshire","FirstName":"Joe","LastName":"Stagner",
"Website":"http:\/\/joestagner.net"},
{"City":"Boston","FirstName":"Jesse","LastName":"Liberty",
"Website":"http:\/\/silverlight.net\/blogs\/jesseliberty"}]

If you squint long enough you can see that this represents what looks like an object that would have this structure:

FirstName, LastName, City, Website

You could consume this in a Javascript function or something in the client script of your web application and nicely iterate through the array of ‘Person’ types, using some human-readable code.

But now you want Silverlight!  And you think to yourself that you need to completely re-write everything to return .NET objects, etc.  Well, not so fast.

JSON Serialization

Because Silverlight 2 supports managed code development, you have some tricks in your bag to leverage existing services that you might not want (or need) to re-write entirely or just right away.  Let’s use the simple example above and assume I now want to use that same service and the same data result in my Silverlight application.  For now let’s assume the endpoint to that service is something like http://foo/mypeople/js.  Most JSON services were a result of using some type of RESTful query model, so essentially your request would likely be a simple GET or POST.

Using Silverlight 2 and the simple WebClient, we can easily get that information from that REST endpoint.

WebClient proxy = new WebClient();
proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy_OpenReadCompleted); 
proxy.OpenReadAsync(new Uri("http://foo/mypeople/js"));

Using WebClient, we essentially open a Stream (which is our endpoint) and get the data back.  You can learn more about WebClient and other services with Silverlight by watching my videos about web services and other HTTP-based communication.  Remembering that service calls in Silverlight 2 are asynchronous, we look at our ‘proxy_OpenReadCompleted’ event and could first get our result (with proper error checking of course) which is of type Stream:

Stream strm = e.Result;

Now with that stream (which is essentially the JSON data now), what do we do?  Enter DataContractJsonSerializer.  Remember, we have this available to us thanks to the CLR being in Silverlight 2.  Before we start to use this, however, our client application must be aware of the Type we plan to de-serialize it back into.  So in our Silverlight application we need to have that type defined as such:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
    public string Website { get; set; }
}

Simple enough.  Now we can complete our asynch handler like this and our Stream is now converted into an enumerable type that we can bind, iterate or do whatever we need to with our data.

void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    Stream strm = e.Result;
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person[]));
    Person[] ppl = (Person[])ser.ReadObject(strm);

    if (ppl.Length > 0)
    {
        // do something with the data
        // bind, interate, whatever
    }
}

That’s it!  With a few lines of code we’ve been able to re-use our JSON service and data from Silverlight.  This might not be the best idea in all of your scenarios but it is possible if you want to transition to other services or make re-use out of your investments already.

A Word About WCF Script-enabled Services

For some of you, if you were already a part of the WCF wave when you created your services, you may have already exposed them as scriptable services using an endpoint behavior that was enableWebScript.  This may have been working fine for you but if you look at the output of that, it might be adding some things that you may not need.  This is because it was intended for ASP.NET AJAX consumption (i.e., it adds “_type” and “_d” stuff).  This is easily rectified to make it a cleaner JSON result as well as make the messages smaller.

By implementing the webHttpBehavior in conjunction with the webHttpBinding type for WCF, you will get a much cleaner/smaller JSON payload for your service.  When implementing this, you’ll want to decorate your service methods accordingly using the WebGet attributes:

[OperationContract]
[WebGet(UriTemplate="people", ResponseFormat=WebMessageFormat.Json)]
Person[] GetListOfPeople();

While I’d argue this isn’t completely necessary to use your existing services, it might make your type parsing a little cleaner and as noted, the message size smaller.  So using this (in fact my endpoint this whole time actually is a WCF webHttpBinding endpoint) the entire code looks something like this:

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(Page_Loaded);
    }

    void Page_Loaded(object sender, RoutedEventArgs e)
    {
        WebClient proxy = new WebClient();
        proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy_OpenReadCompleted); 
        proxy.OpenReadAsync(new Uri("http://localhost:34907/JsonData_Web/People.svc/people"));
    }

    void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        Stream strm = e.Result;
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person[]));
        Person[] ppl = (Person[])ser.ReadObject(strm);

        if (ppl.Length > 0)
        {
            
        }
    }
}

Easy enough.  If you want to know more about the WCF binding types and implementing full REST services in WCF, check out Rob Bagby’s blog…he has a lot of good material there.

Summary

If you have existing services that you’ve enabled JSON responses for already for use in AJAX applications, consider making re-use of them where appropriate.  This may bridge a transition to other WCF endpoints or other service-types while you are writing your Silverlight applications.

I’ve included my sample project used here so you can tinker and you can download the code here.

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.

  1. 6/9/2008 12:25 PM | # re: Making use of your JSON data in Silverlight

    I thought you might enjoy an alternative approach without serializers:

    // A JSON Approach without using a DataContractJsonSerializer

    namespace MySilverLightApplet
    {
    public class JsonHelper
    {
    ScriptObject so = null;

    private JsonHelper(ScriptObject _so)
    {
    so = _so;
    }

    static public JsonHelper Create(string _json_text)
    {
    ScriptObject so = null;

    try {
    so = (ScriptObject) HtmlPage.Window.Eval
    (
    "(" + _json_text + ")"
    );
    }
    catch (System.Exception se) {
    }

    if (so != null) {
    return new JsonHelper(so);
    } else {
    return null;
    }
    }

    public string getString(string _name,string _default_value)
    {
    try
    {
    return (string) so.GetProperty(_name);
    }
    catch (System.Exception se)
    {
    return _default_value;
    }
    }

    public bool getBoolean(string _name, bool _default_value)
    {
    try
    {
    return (bool) so.GetProperty(_name);
    }
    catch (System.Exception se)
    {
    return _default_value;
    }
    }
    }
    }

    // Example Use:

    JsonHelper json = JsonHelper.Create(e.Response);

    string status = json.getString("STATUS","[NO STATUS]");
  2. 8/6/2008 8:37 AM | # re: Making use of your JSON data in Silverlight
    BUILD SOLUTION: ERROR
    I downloaded the sample code and opened the solution in VS. I received an error message in "Page.xaml.cs" that is barking at the "OpenReadCompletedEventArgs" parameter.

    ERROR MESSAGE:
    The type or namespace name 'OpenReadCompletedEventArgs' could not be found (are you missing a using directive or an assembly reference?

    MY RESEARCH:
    For what I've researched, OpenReadCompletedEventArgs is found in the "Windows.Net" namespace. I see it listed in the page.

    Is this a Silverlight Beta 2 issue? Or am I mere a padawan?
  3. 8/6/2008 9:46 AM | # re: Making use of your JSON data in Silverlight
    ArdMan: Yes some classes have moved around since beta1 -- add a reference to System.Net and it should work.
  4. 8/21/2008 10:08 AM | # re: Making use of your JSON data in Silverlight
    I did what you recommended and I received another error.

    Error: The "ValidateXaml" task failed unexpectedly.

    The error mentioned something about a problem with a method "OnApplyTemplate". After a few searches, I found someone else fixed this problem by removing the Reference to Windows.System.Controls.Data and then adding it back. Okay??? (Apparently, the "OnApplyTemplate" is a known issue when migrating from Beta 1 to Beta 2... my bad.)

    After those changes,
    with glee I received... Build succeeded

    Thanks Tim. To celebrate, I'm rejoicing with a caffeinated drink.
  5. 12/23/2008 3:40 AM | # re: Making use of your JSON data in Silverlight
    Hi Tim

    I have downloaded this sample and run the same. It is not working, It throws an error "An exception occurred during the operation, making the result invalid. Check InnerException for exception details."

    How can i fix this and run this sample successfully..???
  6. 3/15/2009 6:30 PM | # re: Making use of your JSON data in Silverlight
    If you aren't running ASP.NET or anything like it on the backend, you are probably still using JSON-based REST'ful services. In this case, you might want to check out a couple silverlight libraries I wrote to make the process less painful. Check out WebBuddy: http://webbuddy.codeplex.com/
  7. 1/18/2010 7:50 AM | # re: Making use of your JSON data in Silverlight
    Hi Sankar,

    Have u find any solution? I'm facing the same error - "An exception occurred during the operation, making the result invalid. Check InnerException for exception details."

    Please reply me the solution - pragati.dukale@revalanalytics.com

    Thanks,
    Pragati

 
Please add 3 and 3 and type the answer here:
First time here? You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting! (hide this)