| Comments

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!

| Comments

When working with Silverlight 2, most will be working with managed code (c#, vb, etc.).  But likely people are working with Silverlight as an additive value to their web application, providing some enhanced user experience to an application.  there may be times where you will still need to call back into the hosting html context.  For then, you'll want to be familiar with two objects HtmlDocument and HtmlPage. 

Both of these objects provide access to the page context hosting your silverlight control.  If you need to seek things in the HTML DOM, you could use the HtmlDocument class.  For example, let's say I need to change the innerHTML property of some <div> element:

using System.Web.Browser;

HtmlDocument doc = HtmlPage.Document;
doc.GetElementById("mydiv").SetProperty("innerHTML", "<b>hello world</b>");

Also, i might want to interact with existing client-side functions, perhaps from client-side frameworks or other library utilities you might have developed on your own.  If I have a function on my page called "foo()" I would invoke it like this:

using System.Web.Browser;

HtmlPage.Window.CreateInstance("foo");

And if I had parameters in a function, like "foo2(theAlert)," I would invoke it like this:

using System.Web.Browser;

HtmlPage.Window.CreateInstance("foo2", new string[] { "tim heuer" });

This may not be the norm with your Silverlight project, but I hope this helps clear some things up!  I am including the "using" statements in my c# samples so you know where in the namespace the class library exists.

| Comments

i've spoken a few times about axosoft.  they are a local ISV that does some great work.  their ceo, hamid, does a great thing every year for his employees (maybe more often) in encouraging and icubating new projects.  they have a core product, but also have incubated some great ideas.  some haven't lasted, but some live strong!  either way it is great to see what kind of ideas their group comes up with.

PureChat is one of those new ideas.  this is an idea that was just released.  it is for asp.net sites and is built using c# and asp.net ajax as well as the ajaxcontroltoolkit.  one of the developers, jonas, writes:

PureChat is written entirely with C# and javascript, against the 2.0 .NET framework. It uses Microsoft's ASP.Net AJAX, as well as selected controls from the AJAX Control Toolkit. Before I go any further, I just want to say that the Atlas (I think I'll always call it Atlas, it's shorter and sounds better) javascript framework really adds a lot of value and productivity for doing any sort of extensive work in javascript. Major kudos go out to that team at Microsoft. (emphasis mine)

very cool.  i just downloaded the free single operator key (this means operator, not incoming chatters) and installed onto my site in < 10 minutes.  i can't get it to play nice with subtext right now, but i'm going to see if the subtext list can help me out (httphandler collision and all).  as an operator i get a complete operator panel that gives me:

    • view of all chats
    • access to transcripts of chats
    • abandoned chats
    • multiple chats

it looks like this:

the end user gets a chat window they communicate with which looks like...well, a chat window.  what's cool is there is nothing for the user to install, and this runs in the browser using asp.net ajax technology.  i was really glad to see jonas' comment about how that framework enabled a lot of things a lot easier for him...that is good to hear.

so if you want to enable web-based chat on your site, you can get a free single operator license or right now they are doing a promotion for $5 for a 5-operator license.  this would be great if you need to provide online customer service in your site/application.  i don't think the intent is to put it on a blog (personal) or anything...at least i don't think that would be a good scenario for me i should say.  the operator has to be logged in.  but for scenarios where you have a product and customers, it would be a good thing to quickly add to your site (or product) and be able to directly communicate with your users.

good work axosoft...i can't wait to hear some behind-the-scenes stories on how it was to leverage the ajax framework for asp.net!  maybe they can add a silverlight UI at some point :-)

| Comments

recently i've been getting a few notes/questions about working with web services and asp.net ajax.  my colleague, rob bagby completed a series of great web casts last year covering the topic of the ajax libraries in detail, one of which deals with web services.  there are also two webcasts that deal with calling WCF services using the ajax libraries.  i highly recommend checking them out!

| Comments

the leaders of the have convinced that phoenix is nice in march (and it is...spring training baby!) and he should visit.  they've organized a super user group meeting and you can find information on when/where here.  it will be hosted at scottsdale center for the arts, which is a pretty killer facility.  i'd recommend carpooling and not messing with the no parking signs (those scottsdale folks like to watch those meters).

having ScottGu come to phoenix immediately after MIX08 is a great thing for the community.  if you couldn't make it to MIX, you'll be able to see some new things from scott in what no doubt will be an exciting, new and learning experience.  there are some great things coming out of his group at MIX and this event in phoenix is a must see.  i'm sure he'll cover some great new web stuff, updates on and we'll all be enlightened by how he still manages to stay close to the code while serving a growing army in the developer division!  be sure to block your calendar now!

i know scott won't be able to cover everything, so we'll ensure that will cover some of the gaps.  be sure to subscribe to the feed to know when we'll be coming back through phoenix -- we'll be updating it soon!