Wednesday, January 28, 2009

Silverlight + RESTful POX

I’m working on a small project for a Swedish company. They need their application be available via web, so it’s time to put that Silverlight knowledge at work, so I decided to use Silverlight for UI technology and have a REST service layer to provide the required data. After all Silverlight and REST services should have no problem. Silverlight experience was great. You have LINQ at your disposal to process the REST results and although the set of available commands in Silverlight is less than WPF, but this makes it is easier at the same time. There was a couple of gatchas along the way, so I’m writing this as a note-to-self.

Service Contract vs. Object Model
The domain model is very simple and consist of a couple of entities, so what REST Services expose as data contracts are more or less the same as what I use in application layer. Silverlight’s class library is not the same as a normal class library so I can not reuse the domain model available in my Silverlight library. This will lead to two set of object models. One for the domain model and the other for the service layer as data contracts. This separation or concern is a good idea, but for this small application it is overkill, but there’s nothing I can do with it. With the help of LINQ2XML the best choice for exposing the contract model is POX (Plain old XML) so result of our services would be in XML parse by LINQ and converted to our domain model.

Unit Testing
Also because of different class library outputs, you can not use unit testing frameworks the way you usually do. This means you can not use xUnit, nUnit, etc. Hopefully there’s a test harness to allow both UI and API level testing when developing Silverlight and it works just like MSTest does. Download the binary files here and read this to know how to add templates to your VS.NET to easily create a test application.

RESTful POX
To achieve this the service contract is decorated with REST attributes, That is a WebGetAttribute if you’re exposing the operation via GET verb or a WebInvokeAttribute if you’re exposing it via POST.

Note : The thing was that exposing IList<T> as a returned result of a service resulted a non functioning service with the following message : “Request Error : The server encountered an error processing the request. See server logs for more details.”. It turned out exposing the List<T> worked. The reason behind this is probably the same thing as exposing an object’s interface via normal (Soap) WCF service which also doesn’t work due to interfaces not being serializable.

So here’s the service contract :

[ServiceContract]
public interface IDataServices
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/Advertisers")]
List<Advertiser> GetAdvertisers();
}
and the implementation is self explanatory. What you get is a service exposed at a URL like http://localhost/Services/DataServices.svc/Advertisers. In order to get rid of the nasty .svc extension you either need to use IIS URL Rewriting Module which is only available on IIS 7 or use IIS Wildcard Mapping plus a HttpModule to make this happen. Read here for complete information.

Note : The .svc extension does not matter from operational perspective. It is computer applications that connect to these URLs after all, but from purists point of view it does matter.

The final part is the configuration which is standard WCF configuration like identifying service and contract, exposing EndPoints, etc. :
<system.serviceModel>
<
serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<
behaviors>
<
endpointBehaviors>
<
behavior name="WebBehavior">
<
webHttp/>
</
behavior>
</
endpointBehaviors>
</
behaviors>

<
services>
<
service name="Reklam.UI.Web.Services.DataServices">
<
endpoint behaviorConfiguration="WebBehavior"
binding="webHttpBinding"
contract="Reklam.UI.Web.Services.IDataServices" />
</
service>
</
services>
</
system.serviceModel>

Submit this story to DotNetKicks Shout it

No comments: