Patterns-Based Silverlight Development – Part IV – Service Layer
In this post, I will be building the WCF Services layer that my client layer will call. I will be using the custom binding made available with Silverlight 3 that enables a decreased message size through encoding the message as binary rather than text. I will also write some code to test this layer.
Adding the WCF Service
Add the web
Before I can add the WCF service that my Silverlight component will consume, I need to add the Web application to my solution.
- Right-Click the Server solution folder –> Add –> New Project
- Under Visual C# –> Choose ‘Web’ –> ASP.NET Web Application
- Name it HelpDesk.Web
- Delete Default.aspx
Add the service
In Silverlight 3, we re-implemented the ‘Silverlight-enabled WCF Service’ template. In Silverlight 2, the template wired up the basicHttpBinding. If you know your WCF, you know that this is the ‘Interoperable Binding’, conforming to the WS-I Basic Profile 1.1. In Silverlight 3, it wires up a custom binding
- Right-Click HelpDesk.Web –> Choose ‘Add’ –> New Item
- Under Visual C# –> Choose ‘Silverlight’ –> ‘Silverlight-enabled WCF Service’
- Name it TicketService.svc
- Add a project reference to HelpDesk.Data. We will need that.
Out-of-the-box Configuration
Let’s take a look and see what the ‘Silverlight-enabled WCF Service’ template gives us out-of-the-box. See below:
You will notice that the bindingConfiguration points to a customBinding. This binding configures a binary message encoder that encodes Silverlight messages in binary on the wire. This binary format is compatible with the Windows Communication Foundation (WCF) binary message encoder. This will result in decreased message sizes. The caveat is that you should revert back to basicHttpBinding if you have non-.NET clients, as this binary format is WCF-specific.
As I stated, this is the out-of-the box configuration. We will need to make some additions in order to allow us to propagate our exceptions to the client. We’ll take a look at that now.
Handling errors with FaultException<T>
I tend to think of exceptions falling into a couple of categories: 1) Business exceptions – exceptions that the user caused and can resolve. Breaking validation rules falls under this category. 2) Technical Exceptions – exceptions that the user did not cause. An example would be that the database is down. 3) Security Exceptions. In our application, we need a way to pass all kinds of exceptions to our Silverlight client. Further, in the event of a validation exception, we need to let the client know which rules were broken.
This was a bit of a challenge prior to Silverlight 3. Now, with some work, we can pass exceptions from our services layer to our Silverlight client with FaultException<T>. Why did I write “with some work”? Well, it is important to understand that Silverlight 3 defaults to using the browsers networking stack for HTTP calls (you can opt in to using another networking layer called the client networking stack). By default, a FaultException will be sent to the client with a 500 HTTP status code. What this means to you is that Silverlight will not be able to access the bodies of these messages. What the client will see is a 404 NOT FOUND.
In order to make this work, we need to configure the WCF service to set the status code to 200 (OK). Don’t worry, it will still be seen as an exception on the client. We will see that in a moment. First, let’s get it set up.
Creating our Silverlight.Patterns Project
Until now, I have been adding some generally re-usable classes to my HelpDesk.Data project and that is just wrong. I am going to add a project that will contain classes that I will be able to re-use over and over again… classes like the RuleViolation or my ValidationException. (I should note that I did have to decorate my RuleViolation class in order to make it serializable). I will also add another class or two here. First, I am going to add the project, move these 2 classes over, change their namespaces and set the appropriate references. I am not going to detail all of that work in this post, as it is grunt work. Please feel free to download the code from this session and you will see the changes reflected there. One last thing, before I move on… I stink at naming assemblies, so if you have any suggestions for a better name than Silverlight.Patterns, please lay a comment on my blog. I am all ears. For now, I will be adding these classes to that project and will use Silverlight.Patterns as the root namespace.
Adding a the SilverlightFaultBehavior class
As outlined in the online documentation article Creating and Handling Faults in Silverlight, we are going to create a WCF endpoint behavior that will set the HTTP status code to 200 for Silverlight FaultExceptions. I will create this behavior in my new Silverlight.Patterns project. Now, I am copying the code directly from the link above, so I am not going to show it all in this post. You are free to download the code for this article and see it, though. I will show the important pieces here.
namespace Silverlight.Patterns.Faults { public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior { public override Type BehaviorType { get { return typeof(SilverlightFaultBehavior); } } protected override object CreateBehavior() { return new SilverlightFaultBehavior(); } ...
You can see above that we created a class called SilverlightFaultBehavior that implements BehaviorExtensionElement and IEndpointBehavior. Below you will see the ApplyDispatchBehavior member from IEndpointBehavior.
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector(); endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector); }
As you can see in ApplyDispatchBehavior, it creates an instance of a type called SilverlightFaultMessageInspector (we’ll see that in a moment) and adds it to the MessageInspectors class of the dispatch runtime. That inspector is doing the work of setting the status code to 200. Take a look:
public class SilverlightFaultMessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { return null; } public void BeforeSendReply(ref Message reply, object correlationState) { if (reply.IsFault) { HttpResponseMessageProperty property = new HttpResponseMessageProperty(); property.StatusCode = System.Net.HttpStatusCode.OK; reply.Properties[HttpResponseMessageProperty.Name] = property; } } }
If the reply is a fault, the status code is set to 200 (OK). This will allow Silverlight 3 to see the fault.
Configuring the Service for the SilverlightFaultBehavior endpoint behavior
We need to update the web.config for our service to add this endpoint behavior. Here is what we need to do:
- Add the extension (directly under System.ServiceModel)
- Add the endpoint behavior (just below the serviceBehaviors node)
- Add the behaviorConfiguration to the endpoint
We are fully configured now. When a FaultException is thrown, it will be sent across with a status code of 200.
Adding the FaultDetail
Remembering back, we want to enable sending a FaultException<T>. What is the ‘T’ part? We want to pass to the caller some information about the exception. What I have chosen to send across in this sample is a Message, a “Type” and the RuleViolations collection.
The “Type” will be a string that the client can use to determine what kind of exception it was. ValidationExceptions will have a type of “ValidationException”, whereas, uncontrollable exceptions will be “TechnicalException”. The RuleViolations collection will return all of the validation violations. Finally, the Message should be client-friendly (you should assume that the message will be directly exposed to the user.
namespace Silverlight.Patterns.Faults { [DataContract] public class FaultDetail { [DataMember] public string Message { get; set; } [DataMember] public String Type { get; set; } [DataMember] public List<RuleViolation> RuleViolations { get; set; } } }
Coding up the Service
Setting up the repository
I have my service configured the way I want it (set up to take advantage of binary encoding and FaultException<T>), so now I need to start writing the implementation. We will start by introducing the concept of our repository to the service, and to provide a hook where we can adequately test the service operations without calling over http.
The template stubs out a simple service operation called DoWork. We will delete that. The next thing we want to do is to add a field for our ITicketRepository. Next, I want to add a couple of constructors. I want an overloaded constructor where I can pass in an ITicketRepository instance. This will provide me a hook where I can pass in a FakeRepository for testing purposes. I also want to implement the parameterless constructor that WCF will call. This will set up the real repository for us. See the code below:
[ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class TicketService { ITicketRepository repository; public TicketService() : this(new TicketRepository()) { } public TicketService(ITicketRepository theRepository) { repository = theRepository; } }
Our test code can now call the overloaded constructor, passing in the Fake Repository. Now we can move on to writing the operations.
Implementing the Fetch Operations
The fetch operations are pretty simple (because we have already implemented the repository and the pipeline. Here they are:
[OperationContract()] [FaultContract(typeof(FaultDetail))] public List<Ticket> GetAllTickets() { try { List<Ticket> tickets = repository.GetTickets().ToList(); return tickets; } catch { FaultDetail detail = new FaultDetail(); detail.Message = "An error occured returning the tickets"; detail.Type = "TechnicalException"; throw new FaultException<FaultDetail>(detail); } } [OperationContract()] [FaultContract(typeof(FaultDetail))] public List<Ticket> GetTicketPage(int pageNumber, int pageSize) { try { List<Ticket> tickets = repository.GetTickets().ByPage(pageNumber, pageSize).ToList(); return tickets; } catch { FaultDetail detail = new FaultDetail(); detail.Message = "An error occured returning the tickets"; detail.Type = "TechnicalException"; throw new FaultException<FaultDetail>(detail); } } [OperationContract()] [FaultContract(typeof(FaultDetail))] public Ticket GetTicket(int ticketID) { try { return repository.GetTickets().ByTicketID(ticketID); } catch { FaultDetail detail = new FaultDetail(); detail.Message = "An error occured returning the ticket: " + ticketID.ToString(); detail.Type = "TechnicalException"; throw new FaultException<FaultDetail>(detail); } } [OperationContract()] [FaultContract(typeof(FaultDetail))] public List<SeverityLevel> GetAllSeverityLevels() { try { return repository.GetSeverityLevels().ToList(); } catch { FaultDetail detail = new FaultDetail(); detail.Message = "An error occured returning the severity levels"; detail.Type = "TechnicalException"; throw new FaultException<FaultDetail>(detail); } }
As you can see, in the event of an exception, we throw a FaultException, providing a FaultDetail. In that FaultDetail, I am setting a client-friendly message, along with a Type of “TechnicalException”. Notice that I have decorated each operation with a FaultContract, passing the type that will pass our error information back to the caller.
Implementing the Update Operation
The update operation is a bit more interesting. Here is the code:
[OperationContract()] [FaultContract(typeof(FaultDetail))] public void UpdateTicket(Ticket ticket) { Ticket t = repository.GetTickets().ByTicketID(ticket.TicketID); FaultDetail detail; try { //Merge the ticket t.ShortDescription = ticket.ShortDescription; t.LongDescription = ticket.LongDescription; t.IsOpen = ticket.IsOpen; t.SeverityLevelID = ticket.SeverityLevelID; IEnumerable<RuleViolation> vs = t.GetRuleViolations(); repository.Save(); } catch (ValidationException vexc) { detail = new FaultDetail(); detail.Message = vexc.Message; detail.Type = "ValidationException"; detail.RuleViolations = t.GetRuleViolations().ToList(); throw new FaultException<FaultDetail>(detail); } catch { detail = new FaultDetail(); detail.Message = "An unknown error occurred updating the ticket"; detail.Type = "TechnicalException"; throw new FaultException<FaultDetail>(detail); } }
Remembering back to our OnValidate partial method that we added in our validation layer, it simply called IsValid to see if there are any RuleViolations. If so, OnValidate threw an exception of type ValidationException. In our update operation, we catch ValidationException. In that block, we fetch the collection of rule violations and set the RuleViolations property on the FaultDetail. In this way, we will pass back to Silverlight the server side validations that did not pass.
Testing Our Service Layer
As I mentioned earlier, by overloading the constructor of my service class, I left a hook in where I can easily test that layer without issuing an HTTP request. I’m going to add a couple of tests now. I am going to put these in a separate test class called TicketServiceTests. You can see the code here:
TicketService CreateTicketService()
{
var repository = Fakes.FakeTicketRepository.CreateFakeTicketRepository();
return new TicketService(repository);
}
Above is a little helper method I created to new up my service class, passing in the FakeRepository.
[TestMethod] public void Updating_A_Ticket_With_Empty_ShortDescription_Should_Cause_FaultException_Of_FaultDetail() { // Arrange var service = CreateTicketService(); // Act var ticket = service.GetTicket(1); ticket.ShortDescription = ""; try { service.UpdateTicket(ticket); Assert.Fail("Validation Issue Should Have Occurred"); } catch (FaultException<FaultDetail>) { Assert.IsTrue(true); } catch (Exception exc) { Assert.Fail("FaultException<FaultDetail> should have been thrown. " + exc.GetType().ToString() + " was thrown"); } }
Again, I have a very verbose method name. You can see from this test that we are validating that the appropriate exception type is being thrown when a rule violation occurs. The next test will ensure that the appropriate RuleViolation is returned with the exception.
[TestMethod] //Added line break in Method name for blog readability public void Updating_A_Ticket_With_Empty_ShortDescription_Should_Raise_FaultException_Of_ FaultDetail_Containing_RuleViolation_For_ShortDescription() { // Arrange var service = CreateTicketService(); // Act var ticket = service.GetTicket(1); ticket.ShortDescription = ""; try { service.UpdateTicket(ticket); Assert.Fail("Validation Issue Should Have Occurred"); } catch (FaultException<FaultDetail> ex) { Assert.IsInstanceOfType( ex.Detail.RuleViolations.Find(rv => rv.ErrorMessage == Ticket.ShortDescriptionRequired), typeof(RuleViolation) ); } }
Summary
In this post, I added the services layer for my little sample app. Here is a brief summary of what I did:
- Added a Web Application Project to the solution
- Used the ‘Silverlight-enabled WCF Service’ template to add a service configured with custom binding that wires up a binary encoder.
- I had to tidy up a bit. I added a project and moved some re-usable components to that project.
- I added a SilverlightFaultBehavior class. This will allow Silverlight to see our FaultExceptions.
- I update the web.config, configuring our SilverlightFaultBehavior class.
- I added a FaultDetail class. This class allows me to pass info to the caller like a Message, the exception type and a collection of validation errors.
- I then coded up the service
- I added an ITicketRepository field
- I added the ability to set a fake repository with an overloaded constructor
- I added the fetch operations
- I added the update operation. In that operation, I caught the ValidationException. In that catch, I set the appropriate rule violations on the FaultDetail.
- I wrote some tests
What’s Next
In the next post, I will likely illustrate how the WCF service can be called from a Silverlight component. I will also illustrate how we are able to pass across exceptions, as well as server-side validation issues. The following post will get into the Service Agent pattern.

Email Me
Enjoying this series very much.
Will you be providing a download of the code for this series?
You can find the downloads as they become available under ‘Downloads’ on the right column of this site. Currently, the code is available via part III. Part IV will be there soon.
Thank you for your work! It really is helping people like me out. I was wondering were you going to illustrate the use of MVVM using the structure you currently are using for this series? This would help out tons! Thank you!
Rob,
Could you share with your thoughts on why you decided to use Soap based WCF vs Rest based WCF? Or you din’t use the .net RIA Services? Or the PRISM2?
I loved your presentation in Las Vegas, I hope you will be visiting US/Las Vegas again. I hope you will not abandon us.
David,
You are welcome. I do plan on illustrating MVVM in this series. The next few are a bit delayed, as I am preparing for 2 talks at DevConnections, but they will be there.
Rob
Marat,
I’d be happy to share. I chose SOAP in this instance because I wanted to illustrate the new custom binding that allowed for binary encoding. I will end this series by illustrating how we could have done most of this with .NET RIA services. Why am I showing this alternative? Some people don’t like the ‘black box’. They like to have full control. Further, given these patterns, it is arguably easier to create a fully testable solution. Don’t let this push you away from RIA Services, however. It is a great solution and arguably much more productive than what we are doing here.
Rob
Thank you Rob,
As always, great answer. These are excelleent presentations. Helps a lot in our daily work.
Thanks for wonderful presentation. It will helps us lot