« Dynamic Silverlight Part 1: Hello, World! | Main | Dynamic Silverlight Part 3: Integrating Silverlight with ASP.NET MVC »

March 07, 2008

Dynamic Silverlight Part 2: Managed JScript and flickr

In part 1 of this series, we looked at how to build a simple Hello, World application using Dynamic Silverlight and IronRuby. In this part we're going to build a more sophisticated application using Managed JScript, IronPython, Silverlight 2, and the flickr API. It lets you find the most interesting 5 photos for your search term using the flickr api:

App

Let's start by walking through an existing JScript app that knows how to display flickr photos on the screen. Download the source code for this tutorial from here:

Download demos.zip

Open a command prompt, navigate to the demos\flickr_start directory and startup the application using Chiron:

chiron_start

Let's look inside of app.xap, which was generated by Chiron:

app.xap

You'll see that the assemblies for managed JScript, and Dynamic Silverlight (DSL) are in the xap, along with some Silverlight controls assemblies from the Silverlight SDK. The complete list of assemblies can be found in AppManifest.xaml:

image

Notice that there is also an assembly called contract.dll - more on this assembly later.

This is a Managed JScript application, and execution begins in app.js.

In Silverlight 1.0 applications, you modified an existing scene by injecting XAML strings, much like how you would use innerHTML in the HTML DOM. In the next part of this tutorial, I will show you how you can do the same thing using just code (and it turns out to be considerably harder than just injecting strings).

The initial scene is defined by app.xaml:

image

This file shows off some cool new Silverlight 2 features. First, notice the two XML namespaces. The c and e namespace prefixes are mapped to types in the System.Windows.Controls, and System.Windows.Controls.Extended assemblies. These assemblies contain our new Silverlight Controls, which are available as part of the Silverlight SDK.

I'm also really pleased to see that we're releasing the source code for these controls under the Microsoft Limited Public License, as well as the test harness that Shawn's team uses to test these controls. Awesome. We're moving in the right direction folks, and we're not done yet.

As you can see, we're using two simple controls: the WatermarkedTextBox (which makes it trivial to create a Search textbox a'la the search widget in all modern web browser), and the venerable Button.

Let's look at the code in app.js to see what happens when you click on the Search button:

image

We bind a JScript anonymous method to the search_button control's click event using a familiar (to C# developers) delegate-style binding syntax. Notice how we're also using a JScript closure to bind to the App instance and the application's root visual.

There's a bit of magic going on in scene.search_text.Text. Here, we're using a DLR feature called member injectors, to dynamically inject attributes onto the scene object. Next, let's look at how we generate our flickr query:

image

Here, we initiate an asynchronous REST all to flickr. QUERY contains a scary flickr REST string that we'll append our search term to. Notice how we again use an anonymous JScript method which functions as a closure to perform an action when the download is complete.

The OpenReadAsync method returns a .NET Stream object which we can pass to Silverlight's built-in JSON serializer. This is where the fun begins :)

The original version of this application was written in IronRuby, and I didn't have a working JSON deserializer handy. While Managed JScript can certainly use any of the widely available JavaScript JSON serialization libraries, I didn't have this luxury in IronRuby. Instead, I used the built-in Silverlight JSON serializer. Unfortunately, this API is designed to be used from statically typed languages. Once we finish implementing the Ruby language, we'll be able to use an off-the-shelf Ruby JSON serialization library. For the time being, however, let me describe the hack that lets you use the Silverlight JSON serializer from a dynamic language.

The inject_photo_list method creates an instance of the JSON serializer, and passes the QueryResults CLR type to its constructor. It then dots into QueryResults to retrieve the properties that we need to retrieve images from flickr.

image

But where did QueryResults come from? At the top of the file, you'll see this call:

image

Recall that we had a reference to contract.dll in AppManifest.xaml. This assembly contains the static definition of the JSON result set from flickr. The source for contract.cs can be found in lib\contract.cs. You'll also find a build script that shows how to compile an assembly for Silverlight, assuming that the paths to the Silverlight SDK line up.

image

The get_photo_url method generates the url that we'll use to get each photo, and you can see how easily we can consume the C# type definitions from Managed JScript:

image

Finally, we generate the XAML for the photo in the BouncePhoto function:

image

Can anyone spot the grotesque hack in this example? This hack will be fixed in the next part of the tutorial. For the time being, however, it works :)

Mixing in a little Norvig

If you look carefully at the screenshot of the completed app, you'll notice that the app suggested another spelling for 'howse'. That suggestion was courtesy of Peter Norvig's awesome naive spell checker. Here it is in its entirety (just 21 lines of Python 2.5 code):

image Wouldn't it be awesome if we could just use this code from our Managed JScript application? Let's take a look at what we need to do to make it happen.

First, we must add a reference to the IronPython assemblies to our AppManifest:

image

Next, we'll need to download Peter's code, as well as big.txt, which is a 6MB 'training file' containing about a million words that is used to train the spelling corrector. Both of these files will be added to our app directory, which means that they will be downloaded within the XAP file:

image

You might be wondering why we didn't just download big.txt from the web. I chose not to because I didn't want to modify Peter's code at all. Files that are downloaded as part of the XAP can be read using the standard IronPython file I/O libraries.

Next, let's look at what we need to do to access IronPython code from Managed JScript:

image

This code loads the managed spell.py module and stores a reference to the correct method. That method is invoked in the spell_check method, which also generates the UI for the suggestion:

image

Managed JScript has very nice cross-language integration, which only requires loading the module and invoking it.

Summary

We took a look at Managed JScript as a language that you can use to write Silverlight apps in the browser. You can access the Silverlight libraries, as well as a custom C# assembly that contained the types we used in the Silverlight JSON serializer. Finally, we saw a nice example of integrating a piece of code directly off the Internet, written in a different language (Python) into your Dynamic Silverlight app.

In the next part of this series, we'll take a look at integrating our application with ASP.NET MVC, and switching the language back to IronRuby on the client.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/t/trackback/2419952/26868644

Listed below are links to weblogs that reference Dynamic Silverlight Part 2: Managed JScript and flickr:

Comments

Very nice. I went through some of the lab version (in Ruby) earlier today, but this is a nice enhancement. I can't wait to see the whole show tomorrow.

Since when does ECMAScript have overloaded += to add event handlers to callsites? Is this a Managed JScript proprietary feature?

Very cool. I'm a bit confused by your (their) usage of the Ms-LPL though. That license says I can ship their binaries with my app, but 3(F) says that it "extend[s] only to the software or derivative works that you create that run on a Microsoft Windows operating system product."

OK, I build my app on Windows using Silverlight, include it in my web site, and now some Linux user surfs to my site and uses the app through Moonlight (same problem with Silverlight on Mac).

Is this a license violation? My app runs on Windows, but without any extra effort on my side, it also runs on Linux and OS X.

If it is a violation, who is the violator?

@RichB: This is an Managed JScript proprietary feature.

@Stefan: We're working on this :)

Hello John,

Thanks for these cool examples. I'm trying to adapt them for IronPython - having some of the text examples as images makes that more painful though!

Michael

@Michael: that's why I have a download link for all the sources at the top of the blog entry :)

Any clue how to use the fancy new controls from *code* rather than XAML? I'm using IronPython and can load controls from XAML (with the appropriate manifest and namespace declarations), but can't import them...

I saw one photography search engine with free photos from Flickr.
Please check this link
http://rotavacx.com

It can help you more than most sites because it has some cool visual search tools. You’ll find what you need in seconds.

Hi,

Great example. I'm having some problems using build.cmd to compile my own c# assembly. Could you provide instructions?

Does anyone know - is it posssible to redistribute chiron as part of a xaml/xap authoring application? Does anyone know what licence chiron.exe falls under?

Thanks

Steve

Post a comment

If you have a TypeKey or TypePad account, please Sign In

Photos

  • www.flickr.com
    This is a Flickr badge showing public photos from John Lam. Make your own badge here.

October 2008

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Blog powered by TypePad