| 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

in my previous post i talked about converting rss data to json using the asp.net ajax javascriptserializer class.  i wanted to use this because i wanted an easier way of interacting with some simple data for a sample i was messing with.  i didn't really see the need to wrap it in a web service call, etc. and in the end i wanted json data.  period.

so why did i want the json data?  to mess with it in of course! what i wanted to do was display my rss feed data in a different way, just out of curiosity.  my goal: display my rss data, in my own handwriting, on a post it note.  in silverlight.  here's what i did.

the font

first, i needed my own handwriting in a true type font (fyi: silverlight supports using open type and true type fonts).  so i went on over to the tablet pc powertoys and grabbed the "My Font Tool" -- this is a tool that allows you to ink the alphabet and then it turns it into a true type font for you.  i did that process and boom, i bring you "Tim Heuer Normal":

Tim Heuer Normal TrueType

okay, great, that step is done.  on to the post it.  headed on over to istockphoto.com for a quick gander at some good stuff and snagged a good one for me.  downloaded it with my credits, used expression design to clean it up and it was ready to go, png-style.

the silverlight application

now on to silverlight...i started using expression blend to create my project.  a simple canvas that had my post-it note image on it and then added some TextBlock elements to represent the rss item title and text:

the hosting page for the silverlight control

now in the page that will be hosting the control i had to add the reference to my JSON-ized rss data using my asp.net handler that i previously wrote about.  i ran into a snag here as i suddenly realized that my json-izer just emitted json data.  that's it.  it wasn't referenced in and javascript variable or anything.  in some situations maybe that is fine, but i needed to "set" a variable to the json data to be able to reference the object later.  i quickly added a param to my json-izer to specify a callback method.  what this would do (if present) would emit javascript that basically called a function.  so if you pass in "c=evalRss" it would result in emitting:

evalRss([{...json data...}]);

this would allow me to set the object data to a variable.  in my hosting page i can now add a reference to my json-izer as such:

<script src="http://blah/rss2json.ashx?u=http://feeds.feedburner.com/timheuer&c=evalRss"></script>

of course i needed to implement the function so i added a simple javascript variable and the callback function:

var rss = null;
function evalRss(objGraph)
{
rss = objGraph;
}

as emiril would say "bam" -- now i have an "rss" object to mess around with...okay, moving on.

setting the textblock elements to the rss data

in my quick sample here, i'm only going to use the latest item in the rss feed, but read later on how you could use them all...remember, sample here folks.

i already had a default handleLoad function that was stubbed out for me and wired up by expression blend, so i'll go ahead and use that.  in the handleLoad function i take the control reference, find my TextBlock elements and set them to my rss data (remember, since my json-izer was a script reference, the json data is already there):

handleLoad: function(control, userContext, rootElement) 
{
this.control = control;
this.header = control.content.findName("ItemHeader");
this.itemtext = control.content.findName("ItemContent");
this.header.Text = rss[0].Channel.Items[0].Title;
this.itemtext.Text = rss[0].Channel.Items[0].Description;
}

okay, whew, got that far.  so when i run the application i get:

RSS Data

yeah, data.  yes, i see it to.  the html.  blech.  i'll have to think about that.  but for now, let's move on.  now i did notice that my text blabbed on beyond the image height and for this sample i didn't like that.  no problem...back to blend.  i created a rectangle (no stroke, no fill) that was the same left/top/width/height as my ItemContent TextBlock.  then with a ctrl+click on both those elements (rectangle, textblock) i headed up to the object menu, select path...make clipping path.  done.  my textblock now is clipped at the shape of the rectangle (you'll not the Clip data added in the textblock attributes).

embedding the font

but wait, i'm not done!  i said that i wanted this in my handwriting.  sweet, i'll just set the textblocks to my font...er...um...wait.  argh.  that's not supported (yet).  no worries there is a way!  here's how to go about it (or at least one way).  first add your true type font to your project.

NOTE: fonts usually have licenses with them.  you need to make sure you understand your font's license before you start embedding it all over the place.  in my case, i contacted tim heuer headquarters and they said it was okay.

now, how do i get the font on the textblock.  here's the process i used.  first, i new'd up a downloader object to get silverlight to download the font to the control and thus have access to it.  i put this in my handleLoad event handler because i want the font to be there asap:

 this.downloader = control.createObject("downloader"); 
this.downloader.addEventListener("completed",
Silverlight.createDelegate(this, this.handleFontDownloaded));
this.downloader.open("GET", "timheuer.ttf");
this.downloader.send();

you'll notice that i added an event listener for the "completed" event of the downloader.  that is where the magic happens with two functions: setFontSource and fontFamily (okay, one function, one attribute).  the SetFontSource (setFontSource in javascript) expects a downloader object as the only parameter.  we're going to use the this.downloader object we created above.  we'll do the setFontSource-ing on our TextBlock elements.  after we call that function, then we can go back to the TextBlock elements and set the fontFamily attribute to the named font value.  i call out named because even though your font file might be "timheuer.ttf" that is not the name of the font family.  all this is done in the handleFontDownloaded event handler and looks like this when completed:

handleFontDownloaded: function(sender, eventArgs) 
{
this.header.setFontSource(sender);
this.itemtext.setFontSource(sender);
this.header.fontFamily = "Tim Heuer Normal";
this.itemtext.fontFamily = "Tim Heuer Normal";
}

so what is happening here?  well silverlight has downloaded the font file using the downloader.  we've passed the downloader reference (which is the sender in the downloader completed event) to the setFontSource property of an element (in our case the TextBlock).  once the font source has been set we set the fontFamily.  so how does silverlight know what to look for?  magic i tell you, magic.  because we've set the font source to a downloader (which downloaded a file), that is the location it is now looking for the fontFamily value...and iterates through that downloader until it finds a match...in our case a true type font named "Tim Heuer Normal" to use.  once we have that i re-run the application and here we have:

RSS Data with Tim Heuer Font 

awesome. 

what about more than one font?

but what if you wanted multiple fonts?  would you need multiple downloaders?  no.  you see, the downloader supports compressed (zipped) files.  and it doesn't just have to be fonts.  it could be a mixture of media, fonts, xaml assets, etc.  in fact, that is how zero gravity gets all its assets for the game prior to play.  if you had a zip file that you added the "timheuer.ttf" file into, really the only thing that would change would be the downloader.open() function to downloader.open("GET", "myzipfile.zip") -- your setFontSource and fontFamily code wouldn't change!  if i had two fonts in the zip file then i could change the header to something like this.header.fontFamily = "Knockout C" or whatever other true type font is in the zip file.

having some fun

now that we have all that wired up, we can move things around and make it look like i posted a note just sticking it on the frigde or something -- not linear.  i can simply add a rotatetransform on my canvas and i'll get:

the fonts, etc. change no problems.

so my little quest was complete.  i got my handwriting in my rss feed in silverlight.  yippeee.  now if only i had an investor.

the issues and controls

there were issues as you saw.  first the characters.  the "my font" tool doesn't ask me to write every possible characters, so if i used some that weren't in my font, blech.  the point here is that you'd likely use a cool font that was professional.

the html -- yes.  i'll have to think about this one as i do have a use for this concept coming up.  my rss feed is html.  silverlight doesn't really have an "html" survace...it isn't interpreting <p> as a paragraph break, etc.  in this sample, it might be problematic, but other areas where you have text in textblocks and are embedding fonts you shouldn't have that issue.

what if you wanted to display all rss feeds?  would you need 10 textblocks and set them 10 times?  well, kinda.  my suggestion here is to use the control approach.  i already have the xaml for my post-it display.  i could take that, put it in a control, stuff it into the zip file with my font and have a control i could reference.  (for an example screencast on user controls in v1.0 see this link) for example, i could encapsulate the post-it in a control that looked something like this:

RssNotebook.RssItem = function(control, target, header, desc, x, y, downloader) 
{
this.header = target.findName("ItemHeader");
this.itemtext = target.findName("ItemContent");


this.header.setFontSource(downloader);
this.itemtext.setFontSource(downloader);
this.header.fontFamily = "Tim Heuer Normal";
this.itemtext.fontFamily = "Tim Heuer Normal";
this.header.Text = header;
this.itemtext.Text = desc;
target["Canvas.Top"] = y;
target["Canvas.Left"] = x;
}

then i can extract the RssItem xaml, put that in a file and add it to a zip with my timheuer.ttf file.  I now have a zip with RssItem.xaml and timheuer.ttf.  now with that i can alter my downloader completed event to look like this:

handleFontDownloaded: function(sender, eventArgs) 
{
var top = 0;
for (var i=1; i<3; i++)
{
var postit = this.control.content.createFromXaml( sender.getResponseText("RssItem.xaml"),
true);
this.root.children.add(postit);
new RssNotebook.RssItem(this.control, postit, rss[0].Channel.Items[i].Title,
rss[0].Channel.Items[i].Description, 0, top, sender); top += 100;
}
}

so what you see happening here is two things.  first let me be clear that this is still a sample, and for the control part i added a scale transform to reduce the size of the image just so i could display it here.  okay, what is happening is that i'm iterating through two of the rss items and createing the RssItem control within that iteration (createFromXaml) getting the xaml out of the downloaded zip file.  then in that control i'm doing the fontSource-ing and fontFamily-ing for the TextBlocks represented in their control. 

pretty cool huh?

i hope this may help with some things.  if not, ask me questions.  i've included the sample code in this post to help you out.

File: RssNotebook-single-style.zip</> (sample using single style)
File: RssNotebook-control-style.zip</> (sample using control style with zip file)

if you have any suggestions for other things you'd like to see, keep them coming!

| Comments

i was working on a little sample and wanted to make it a bit easier on myself to work with my rss data.  my thought was to use the JSON format for the data and that way i could get at the data in super-cool-ajaxy-type ways.  what was cool was what i found as i began searching.

ASP.NET Ajax provides a class library to javascript!  in System.Web.Script.Serialization.JavascriptSerializer is where you will find your magic.  the JavascriptSerializer can be used on anything that uses XmlSerialization.  sweet.

so now all i had to do was take my RSS data (already in good xml format) and serialize that to xml.  once the rss is in a strongly typed respresentation using XmlSerialization, then i can pass that object to the JavascriptSerializer and voila...json formatted representation.

so my rss:

<?xml version="1.0" encoding="UTF-8"?> <channel> 
<title>Method ~ of ~ failed</title> <link>http://timheuer.com/blog/Default.aspx</link>
<description>ramblings from the digital underbelly</description>
<language>en-US</language> <copyright>timheuer</copyright>
<managingEditor>[email protected]</managingEditor>
<generator>Subtext Version 1.9.5.176</generator> ...

becomes:

{"Version":"2.0","Channel":{"Categories":[],"Cloud":null,
"Copyright":"timheuer","Description":"ramblings from the digital underbelly",
"Docs":null,"Generator":"Subtext Version 1.9.5.176", ...

wicked.  i put this in an asp.net handler file for me so now i can easily reference some rss data and immediately get back json data to work with, something like:

<script src="http://mysite/rss2json.ashx?u=http://feeds.feedburner.com/timheuer"></script>

you can get an rss serializer with this function built in over at piyush's blog.  very cool, now i can move on to my next step...

| Comments

sitting in a session watching /:

    • getting input from an html input element...
    • write a ruby block...
    • responding to a c# event...
    • calling a visual basic function to get JSON serialized information...
    • then doing some other stuff in python...
    • executing animation with javascript...

...all in a single app, powered by the dynamic language runtime in Silverlight.

i think i just peed my pants.

| Comments

if you are a web developer, you most likely want all possible tools available to you.  and there are some great ones out there like firebug, ie development toolbar, etc.  if you are an asp.net developer, you most likely know about the best helper tool by called the ' which is implemented as a browser helper object for internet explorer.

nikhilk has evolved his tool over time and in the latest version has awesome support for reading JSON encoded information and visual representing them in a helper way so that you can see what is going on.  as an example, here is one such view:

well, those that have been running vista may have been running into problems using nikhil's tool if you are either running under UAC-enabled or possibly running internet explorer as an administrator (run as administrator mode).  this may have resulted in the web development helper a) not even showing up under the tools options in IE and/or b) when you enable the toolbar, all you see is a gray area with nothing helpful :-).

well, after reading a bit into one persons attempts, i decided to quickly hack a reg setting to see if it will work (i was one such person that couldn't get it working under vista).  i'm happy to report that my results are favorable and i now have the great web development helper toolbar working under vista with UAC disabled.  yippee...i'm so happy i could cry.

i'm sharing the love so here is my reg hack file.  rename to .reg and merge into your registry.  WARNING: MODIFYING THE REGISTRY COULD CAUSE DAMAGE IF YOU DON'T KNOW WHAT YOU ARE DOING...PERFORM THIS TASK AT YOUR OWN RISK!