Mad, Beautiful Ideas
WCF with Silverlight

We've been using Microsoft's Silverlight and the Windows Communication Foundation for the last several months as the User Interface and Web Service framework for our just-launched course schedule proofing project, ROOMS. As people have been doing the scheduling off of paper since long before Washington State University was known as such, people have been really excited at the possibility of working with a newer technology.

I'm not going to be talking too much about Silverlight itself, as I've been the developer responsible for the back-end work since I got brought onto this project. Silverlight isn't a bad framework, by any means, but I do personally favor interface technologies that don't require plug-ins. That said, the interface Silverlight has allowed us to create would have likely been harder without the benefit of Silverlight.

For building Web Services, WCF has a lot going for it. You're interface for the service is easily provided in a single interface class, your Data Transfer Objects (DTOs) decorated with a few attributes, and your transport protocol can be changed with a few simple configuration options. It's really flexible. We're using it not only for our webservices, but also to communicate with a Windows Service which handles several long running tasks, saving us from triggering those events with a timer.

However, there are some unfortunate side-effects of pairing a WCF web-service with Silverlight that aren't necessarily obvious.

Security

Our application needs to run over a Secure Shell connection, so that we can protect the user's login state, and eventually any confidential data that becomes a part of this application. While Silverlight supports cross-domain web-service requests, it does not appear to support these over a secure link. The article linked does refer to Silverlight2 Beta 1, but it appears to me that this was not changed for the RTW.

Because of this lack of Secure Cross-Domain Web Services, you're required to host your WCF services in IIS, which requires some modifications to your web.config file, which I have posted about here. More troublesome, is that if you do need secure webservices from a cross-domain source, this technology forces you to take steps like we need to with modern AJAX applications, wrapping up a webservice 'locally' so that it can be called the way we need it to be. Lot's of unnecessary work there.

The other step, that is easy to forget, is that the Security method needs to be set correctly on both sides of the connection. In your ServiceReferences.ClientConfig file, as well as your web.config, your security is likely set to 'None'. This must be set to 'Transport' for SSL to work, but more importantly, if you set it to 'Transport' it will only work over SSL. You could set up a different, insecure, Endpoint in your web.config if you wanted to offer both, but this is extra work that seems, to me, to be somewhat more inflexible than necessary.

Configuration

The biggest challenge we've had using WCF for our services has been maanaging the configuration steps. Anytime we add a new method to our service, we're forced to rebuild the Service Reference in the Silverlight config. There is no obvious way to automate this as a build step, partially because our web project depends on our Silverlight app, and the web server must be running in order to update the service reference. In an ideal world, I'd build my services, start up the web server, load the service references, and then finish building the Silverlight. I've looked into doing this with MSBuild and svcutil, but it does not appear to be that simple.

The tools Visual Studio provides in 2008 are also insufficient. Generally, we are forced to delete the entire service reference and re-adding it, and even then I'll occasionally end up with strange errors that are non-obvious as to their source. The way the configuration management works to date feels like a house of cards, and I've periodically lost significant amounts of time to rebuilding service references.

To save time and configuration, we've opted to store our DTOs in a shared assembly between our Web project that hosts the services and the Silverlight project. To support this, we first attempted to create the DTO project as a Silverlight project, and merely add a reference to both projects. Regrettably, this does not work. Silverlight is not .NET 3.5 (which introduced WCF), and while there are a lot of similarities between the two technologies, the assemblies the Silverlight project links that declare the necessary attributes are not the same version as used by .NET 3.5 and WCF, so the linking fails.

We got lucky on this issue, and we were able to use Visual Studio to create links from the Web Project to the DTO files, so we can build them once for the Silverlight and once for the WCF without breaking any code. Cumbersome, yes, but relatively easy, once you know what to do. In my opinion, it's completely worth moving your DTOs into a seperate assembly like this, if for no other reason than it will be more conducive to performing Unit Tests later.

This does leave us with one major problem, namely, how do we keep our service references up to date as part of our build process? I haven't quite figure that out yet, but the procedure we are most likely going to use is as follows:

  1. Examine WCF ServiceContract Interface.
  2. Find all OperationContracts under the Interface, and generate Callback Events and ASync Call methods for all of them
  3. Write out source to reference file, to be included in Silverlight project

We're investigating a few methods to accomplish this. We met a guy at the Seattle Code Camp who had written XSLT's to convert a chunk of XML into the Interface files, and that's not necessarily a bad way to go. I could even use this to generate my DTO classes. I am investigating the possibility of doing a simple compile on the code itself, but I suspect the XML route would be easiest. Plus, that way our Interface files in the WCF project will be auto0generated as well. Plenty of interesting possibilities there. Once I've got it written, I'll likely be sharing the solution we arrived at.

Both Silverlight and WCF are interesting technologies. Personally, I'm likely to do more WCF, but that's largely because I'm a back-end systems developer, and Silverlight is definitely aimed at the UI-set. I know my limitations.

As I often think when dealing with Microsoft technologies, I wish they integrated a little more cleanly. Still, Silverlight and WCF are very usable together, and if you're still writing web services in ASMX files, you owe it to yourself to at least consider WCF. I suspect it may make your life a lot easier in the long term.