SDN Conference - Demo Code

Silverlight Logo

I just finished up with my four talks at the SDN Conference outside of Amsterdam and I had a great time. For anyone who missed it, you missed a great time. Amsterdam 026

I had four sessions ranging from cloud computing to Silverlight 2. For the attendees I wanted to give you a chance to download the demo source code I wrote for the sessions.  You can find it here:

If you have any questions, drop me a line.

All Quiet...

Silverlight Logo

Its been quite quiet on my site these last week or so. I am traveling doing a couple of European conferences so my blogging is light. I do expect to deliver my new edition of my ScreenCast (Shawn Wildermuth's Dirty Little Secrets) this friday and I'll have a completely wrap up of the conferences once they are complete. Stay tuned for a lot more content in the next week or so.

Silverlight and ADO.NET Data Service Operations

Silverlight Logo

In building my Silverlight RC example using ADO.NET Data Services for Entity Framework and NHibernate I ran into what I think is a common pattern.  I am writing an editor for XBox game data. The model for this data uses decorator tables in the database which are modeled as a common "Product" class and derived "Game", "Console" and "Accessory" classes.  In the application I am using paging to only look at fifty results at once. This works fine on both sides. 

But one of the pieces of information I wanted was a list of all the Game Genre.  This became problematic as ADO.NET Data Services wanted me to retrieve all 880 games in order to get a list of these Genres (of which there are only 20 some odd). The whole idea of using paging is go avoid the huge overhead of bringing down the whole entity. Interestingly when I executed a LINQ query that used projection into non-entities, the query wasn't supported as projection isn't allowed in the ADO.NET Data Services URI model (which the client uses).

What ADO.NET Data Services does allow is to create Service Operations (e.g. WebGet or WebInvoke) on the Data Service to extend the model for specific cases. There are some limitations (must return IEnumerable<T>, IQueryable<T> or void) but this works pretty well. The difference between returning IEnumerable and IQueryable is whether system queries can be applied to them.  Returning a fixed list (my need) meant to return a IEnumerable<T> list. Intersting that ADO.NET Data Services support returning an IEnumerable<T> of primitive types.  For example my operation was spec'd as:

[WebGet]
public IEnumerable<string> Genres()
{
}

This works and returns a simple XML file with the primitive values.  But alas the Silverlight Data Service Client doesn't support non-entities. I tried using the DataServiceContext.BeginExecute() to call this service and it threw an exception that it couldn't materialize non-entity classes. Hrmph!

This was a case where adding a quick web service call to get this data on the server and return it would have been the easy road, but that's not how I roll, is it?

After confirming this behavior with the Data team, I decided to write an extension to the DataServiceContext class to support this.  In this little piece of code, the same pattern of calling DataServiceContext.BeginXXX is used. To make this work I simply use the HttpWebRequest class to do a simple GET to the server's URI syntax and use LINQ to XML to convert the data into the simple types (String in my case).

I've started to help out with some new ideas on the CodePlex SilverlightContrib project so I thought this was the perfect place for this code.  Its not packaged up yet in a build (and probably won't be until sometime after RTW ships) but if you want to grab it you can grab the latest checkin I made:

SilverlightContrib ChangeSet 41005

I'll be shipping this new demo as soon as RTW ships (its not done yet). Look for the announcement here.

I am an MVP!

Silverlight Logo

I am proud to announce that Microsoft hasn't come to their senses yet and decided to renew my MVP status for another year. Being an MVP has been a great experience for me and I really appreciate the program. Five years into the program and I couldn't be happier.

Atlanta Geek Dinner - October 23, 2008

Silverlight Logo

To coincide with my Atlanta Silverlight Tour Stop, we will be holding the Geek Dinner at Papadeaux's in Alpharetta on October 23, 2008. Please visit the GeekDinners.com site to RSVP and get directions:

Pappadeaux Seafood Kitchen
10795 Davis Dr.
Alpharetta,GA 30004
USA
770-992-5566

Silverlight Tour Goes RC

Silverlight Logo

Don't miss your chance to take the first Silverlight Tour stop that is supporting the impending release of Silverlight 2.  Starting with the Atlanta, Georgia - October 22-24th stop of the Silverlight Tour, the course will be taught using Silverlight 2 RC (or the full release once that happens).

The Silverlight Tour is a three-day intensive Silverlight 2 workshop that teaches the basics of designing Silverlight 2 applications including design, development, services, control development, control skinning and security.

New Information on WebClient in Silverlight 2

Silverlight Logo

After digging and some prodding by a PM at Microsoft, I realize that the relative URI story in WebClient is different that I expected.  I am not sure whether this changed from previous versions but Beta 2 and the RC this is the way that Relative URI's work in WebClient:

  • WebClient supports a BaseAddress property (read/write) that by default contains the path to the .xap file (though you could replace it with HtmlPage.Document.DocumentUri.ToString() to resolve to the current page).
  • It uses the BaseAddress to calculate the relative URI
  • This is not the same as the Image/Media "Site of Origin" relative URI problem (see my post about that here).
  • In most cases a relative URI in WebClient will do the right thing and supporting the BaseAddress will allow you to change the basis for the relative URI's pretty easily.

Note that the WebRequest classes (BrowserHttpRequest specifically) does not support relative URI's so if you want to use that class instead of WebClient, you'll have to do your own relative URI resolution. 

The Silverlight Tour in the UK

Saffron Interactive

I am happy to announce our newest partner for the Silverlight Tour: Saffron Interactive. They will be teaching the Silverlight Tour materials in the United Kingdom including their first class on December 3-5, 2008 in London, England.

For this first class I will be teaching the class so if you are in London and have been hoping to take the class from me, this is your one opportunity as Saffron will be teaching all subsequent classes. 

WebClient vs. WebRequest in Silverlight 2

Silverlight Logo

When making web requests in Silverlight 2, its easy to start with the simple WebClient class. In fact, it supports making simple requests (DownloadStringAsync and OpenReadAsync) as well as uploading through the class. On the other hand there are some that swear by the WebRequest route. What's the big difference?

Let's start with WebRequest. The pattern for WebRequest is to call WebRequest.Create:

Uri url = new Uri("http://localhost:8889/Silverlight.js", UriKind.Absolute);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);;

Notice that we are actually using a HttpWebRequest object and casting the return value of the Create call. In reality this object is a BrowserHttpWebRequest object. This class represents a web request in Silverlight 2 (since all requests are actually routed through the browser's networking stack). The reason for this is to make sure that any requests are part of the page.  This means that when you make a request in Silverlight 2 it is bringing with it the same Session ID and cookies.  This also means that for large sized requests, the user may cancel the request.

To execute the request, we need to get a WebResponse object that contains our results of the request. To do this, ordinarily you would call the HttpWebRequest's BeginGetResponse method:

req.BeginGetResponse(new AsyncCallback(WebComplete), req);

This method specifies that you create an AsyncCallback object that describes the callback once the request is complete.  The WebComplete object in the AsyncCallback is actually the method to call (though you could use a delegate or lambda here):

void WebComplete(IAsyncResult a)
{
  HttpWebRequest req = (HttpWebRequest)a.AsyncState;
  HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(a);
  Dispatcher.BeginInvoke(() => status.Text = "Downloading...Done.");
}

Note that we're retrieving the request from the AsyncState and then calling EndGetResponse to complete the operation. The most important thing to understand inside this callback is that it does not happen on the UI thread so any calls to update the UI will result in InvalidThreadAccessExceptions. Typically this means using the Dispatcher to call the UI thread as necessary (as shown). In addition, the response contains a stream that contains the results of the request. To retrieve the data, you need to write code to dig it out of the stream as necessary...not hard, but another step.

In contrast, the WebClient class performs this operation very differently. First, it supports two different request styles: DownloadString and OpenReadDownloadString support the ability to retrieve a string with the contents of the request. The OpenRead style returns a Stream instead. This way you can decide if you need a simple way to retrieve just a string, otherwise you can use the tried and true way of consuming a Stream.

Another change is the WebClient class uses events not AsyncCallbacks to complete the asynchronous model.  The events and execution start of each of the styles are paired up with Completed events and Async execution methods. For example, to make a request with the WebClient with the DownloadString style: 

WebClient client = new WebClient();
client.DownloadStringCompleted += 
  new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("/Silverlight.js", UriKind.Relative));

The other big difference is that the WebClient class handles the context switch for the user. What this means is that when the event is fired, it is always called on the UI thread. So your event handling code can update the UI directly as so:

void client_DownloadStringCompleted(object sender, 
                                    DownloadStringCompletedEventArgs e)
{
  status.Text = "Downloading...Done.";
}

So what's the verdict?  There is none. They both are fine to use.  In fact, under the covers the WebClient class uses the BrowserHttpWebRequest class so that it does not matter. If you find the WebClient class easier to use, go ahead. But if you are already familiar with the HttpWebRequest-style classes and AsyncCallback objects, continue to do what you're comfortable with. Just understand the differences between these workhorses of Silverlight 2.

What do you use?

Silverlight 2 Tools Release Candidate Now Available

Silverlight Logo

In case you haven't heard yet, Microsoft announced that a Release Candidate of the Silverlight 2 tools are now available. You can download it now here:

Included is the Silverlight 2 SDK, Silverlight 2 Visual Studio Tools, the Silverlight 2 Developer Runtime and Blend 2 SP1 (was called Blend 2.5 but is now a patch to Blend 2 instead). Note that the Release Candidate should give you time to get your applications ready for release, but that the runtime won't be generally available on the Internet until Silverlight 2 reaches release. Unlike when Silverlight 2 Beta 2 was released, you won't have to rush to fix your applications.

This means there is no "Go-Live" license with the Release Candidate, but you can modify your code to be compatible with the release and be ready to deploy them once the RTW (Release to Web) happens (which hopefully will happen soon).

Note: Beta 2 users will automatically be upgraded to the RTW version once its available.

Also make sure you look at the Breaking Changes document to see what's changed.  The changes are not dramatic but there are a couple of surprises:

  • By default all rendering is now pixel aligned.  This should allow you to avoid that sub-pixel rendering issues that plagued earlier releases.  You can enable sub-pixel rendering if you need it.
  • Blend 2 SP1 now supports the Font Manager (so you can embed and even subset fonts automatically).
  • New controls were released (ComboBox, ProgressBar and PasswordBox).
  • Fonts now must be assembly resources (no more free floating fonts in the .xap file).
  • Custom Control XAML files now must exist in a themes folder instead of at the root of the project.

For all the changes, please review the Breaking Changes document.

I am currently converting all my examples to RTW and they will ship when the release happens. 

More Rants