2005 2006 2007 2008 2009 2010 2011 2015 2016 aspnet azure csharp debugging exceptions firefox javascriptajax linux llblgen powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

Understanding WCF Faults in Silverlight

If you like this document, please consider writing a recommendation for me on my LinkedIn account.

Contents

Introduction

Regardless of what platform you are working with, you need some mechanism for dealing with errors.  When it comes to using WCF in Silverlight we are all very fortunate to be able to build out solutions on the back of many tried and true techniques for error management. When working in this context, we are dealing with basic SOAP messages (that is, XML) and WCF's abstraction of those messages, neither of which are new to the world.

If you haven't done so already, you should read the first part of this document entitled Understanding WCF Services in Silverlight (here after "previous document").  You may consider this document an appendix to that one.  That document explains WCF and its integration into the world of Silverlight from a very low level. This document extends that one to explain error management in the world of Silverlight 3. Understanding of the previous document is a prerequisite for understanding this one.

SOAP Review

Before we take a look at error management over SOAP services, we will take a moment to review SOAP messaging. SOAP messaging is based on the concept of sending SOAP messages back and forth between client and service. A SOAP message is the package by which a client and a service communicate. Web services (a.k.a. SOAP services) are not "connected" like a chat channel. Instead, they are "disconnected" like an e-mail system. The client sends the service a message and the service, optionally, sends the client message back (depending on if the client requested a message; one way messaging is very common). Below is a sample message sent from a client to the service:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetPersonData xmlns="http://www.netfxharmonics.com/service/Contact/2009/07/">
      <personGuid>F488D20B-FC27-4631-9FB9-83AF616AB5A7</personGuid>
    </GetPersonData>
  </s:Body>
</s:Envelope>

Essentially, this message is calling the "GetPersonData" operation on the service, sending "personGuid" as a parameter. This is stored in the message body (which is distinct from, say, a message header, which is not present in this example). The body is then stored in an envelope. When this message is sent via an HTTP POST to, for example, /Person.svc with the SOAP-Action HTTP header set to the name of the SOAP operation, WCF calls the appropriate operation (set by the SOAP-Action HTTP header).  For more information on the mechanics of WCF and how to work with WCF directly see my XmlHttp Service Interop series at http://www.netfxharmonics.com/2007/05/XmlHttp-Service-Interop-Part-3-XML-Serialization).

Here is a message the service could possibly send back to the client:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetPersonDataResponse xmlns="http://www.netfxharmonics.com/service/Contact/2008/11/">
      <GetPersonDataResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <City>Unknown</City>
        <FaultDetail i:nil="true" xmlns:a="http://schemas.datacontract.org/2004/07/General.Service"/>
        <FirstName>John</FirstName>
        <Guid>89DEA4C5-84A0-45db-A60D-CE49F214EA50</Guid>
        <LastName>Doe</LastName>
        <PostalCode>66062</PostalCode>
        <State>KS</State>
      </GetPersonDataResult>
    </GetPersonDataResponse>
  </s:Body>
</s:Envelope>

Here we have the data for "GetPersonData" in a result object, wrapped in a response container. This is then, once again, wrapped in a standard SOAP body, inside a standard SOAP envelope. Pretty simple stuff. Someone sends a message, the receiver sends something back. The question now becomes... what happens when something goes wrong?

Handling Errors

When doing error management with SOAP-based WCF, you are doing just that: error management. You are NOT doing exception management. Exceptions don't exist over the wire. How can an exception from WCF being handled by a PHP client? How can System.InvalidOperationException be handled by a Java client? These scenarios make no sense. Therefore, in the world of SOAP services, you have no exceptions. Instead, you have a concept called a "fault".  A fault is a SOAP error.  WCF, Java, and PHP can all deal with SOAP (since SOAP is just XML), thus, they each can deal with faults with no problem. Given this, we may adjust our terminology at this point from "error management" to "fault management".

In reality, a fault is nothing more than a piece of XML formatted in a specific way. One side sends it, the other side receives it. It's a really simple setup. (As a side note, please keep in mind that this is not a document on the internal mechanics of SOAP. That's a discussion for a different document. Fortunately, though, the understanding of faults in SOAP doesn't require deep SOAP knowledge.)

When an exception is thrown in a SOAP-based WCF service, typically a fault is sent over the wire. A SOAP-based client (be it WCF, WCF in Silverlight, PHP, or Java), then obtains it, parses it and handles it accordingly. So what's a SOAP fault look like? (you'll see later that this is an example of a very poor practice, but it's a good fault example.)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Really descriptive message here.</faultstring>
      <detail>
        <InvalidOperationException xmlns="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
          <ClassName i:type="x:string" xmlns="">System.InvalidOperationException</ClassName>
          <Message i:type="x:string" xmlns="">Really descriptive message here.</Message>
          <Data i:nil="true" xmlns=""/>
          <InnerException i:nil="true" xmlns=""/>
          <HelpURL i:nil="true" xmlns=""/>
          <StackTraceString i:nil="true" xmlns=""/>
          <RemoteStackTraceString i:nil="true" xmlns=""/>
          <RemoteStackIndex i:type="x:int" xmlns="">0</RemoteStackIndex>
          <ExceptionMethod i:nil="true" xmlns=""/>
          <HResult i:type="x:int" xmlns="">-2146233079</HResult>
          <Source i:nil="true" xmlns=""/>
        </InvalidOperationException>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Notice that even this fault is a SOAP message: the contents are in a SOAP body, wrapped in a SOAP envelope. So, all we really did is use a concept we already knew and added something to it. By sending a "Fault" XML element in a message body, you are effectively telling the client that some error occurred on the service-side. This is a well-known pattern that all SOAP services follow.

If you look closely at this SOAP message (which, of course, is also a fault), you will notice that the "Fault" element has three children: "faultcode", "faultstring" and "detail". You may recognize some parts of this specific fault.  That is, you see the name "InvalidOperationException" as well as the "Message", "InnerException", and other elements as well-known properties of exceptions. Keep in mind, though, that none of these have anything to do with faults. These are in the "detail" section of the fault, not in any part that actually matters.  Clear as mud?

Faults don't rely on the detail element. The information in this block is simply for the end developer to obtain custom information. Since WCF doesn't rely on this information, neither should you (i.e. it won’t always be there). A fault is defined by the "faultstring" element, not the "detail" element. The "faultstring" element contains is the actually message that you will want to look at when debugging.

Not even the "faultcode" element isn’t directly used by most people. This is a well-defined enumeration with the possible values of "Client", "Server", "VersionMismatch", and "MustUnderstand" (prefixed with the XML namespace). These help you to get some idea of the category of error that occurred, but, in the majority of cases, you won't be working with it directly.  This is all to reinforce the fact that it’s faultstring that contains the actual error, not faultcode or details.

Applying to WCF

In the world of WCF for .NET, all of this is essentially internal mechanics that most mid-level or entry-level developers will only see on a senior-level developer's whiteboard (i.e. they won't use it directly). This is because WCF knows to look for faults and knows how to handle them: it will take the content from faultstring and set that as the Message in a System.ServiceModel.FaultException object. This instance of a FaultException object is developers directly work with.

Now pay attention very closely: you can't just throw an exception in a WCF service and expect it to show up on your client (or to show up over the wire for that matter!) Why is this? Thikn about it... do you really want an exception which contains the entire stack trace and, therefore, a snapshot of the private internal mechanics of your system thrown to a client computer? Obviously not. Since WCF knows is a horrible security violation to send stack traces over the wire, it's not going to allow this.  In fact, that fault SOAP-message shown early is hopefully a picture from fiction, not reality (you kind of figured there were a lot of unneeded xml elements, didn't you?)

What you actually do, is you throw one of two special exceptions: System.ServiceModel.FaultException or System.ServiceModel.FaultException<T> (which inherits from the first one). When you throw an exception which isn't one of these, like System.InvalidOperationException, you will see the following over the wire (i.e. throw new System.InvalidOperationException("This is my error message.")):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
      <faultstring xml:lang="en-US">The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

You may think "not pretty". Trust me, that IS pretty. Ugly would be showing your internal stack trace over the wire. Thank you WCF for protecting us from ourselves.

Now, if you throw System.ServiceModel.FaultException instead of System.InvalidOperationException (i.e. throw new System.ServiceModel.FaultException("This is my error message."), you will see this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">This is my error message.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

Very simple and to the point. You told it "This is my error message." and it sent "This is my error message." Can't get much simpler than that.  In fact, the simplicity stays even when you work with the exception on the client side.  Over there, the client will also have a FaultException.  The “faultstring” from the SOAP message will be places into the Message property of the FaultException object on the client.  An example of this will be shown in a bit.

Let's make this a bit more complex (read: more useful/powerful) by changing things up slightly.

As I've said, there are two fault exception types in WCF: one generic, one not. Use of the generic one allows you to send more information to the client by allowing entire objects to be serialized over the wire as part of the fault "detail" element. To see an example of this, take a look at the following custom type:

namespace Contact.Service
{
    [DataContract]
    public class FaultDetail
    {
        //- @ErrorCode -//
        /// <summary>
        /// Custom business-specific error code.
        /// </summary>
        [DataMember]
        public Int32 ErrorCode { get; set; }
        //- @Type -//
        /// <summary>
        /// Specifies the type of error.
        /// </summary>
        [DataMember]
        public String Type { get; set; }
    }
}

Now, instead of throwing the non-generic fault exception, let's throw the generic one, using the above type as the generic parameter. For example:

//- @GetPersonData -//
public Person GetPersonData(String personGuid)
{
    //+ ...validation here...     
    FaultDetail faultDetail = new FaultDetail
    {
        Type = "Validation",
        ErrorCode = 63873928
    };     //+ throw     
    throw new FaultException<FaultDetail>(faultDetail, "Invalid guid.");
    //+ ...more logic here...
}

Given this, we now have this over the wire:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

As you can see, using the generic FaultException type, you can send all kinds of stuff over the wire.

Fault Contracts

While this is great for dynamically typed systems (i.e. PHP and JavaScript), we don't yet have a complete solution for strong-typed ones (i.e. .NET). What’s that? Again, think about it: How does the other end know what type is "FaultDetail". Is that ABCCorp.Web.FaultDetail? ABCCorp.Service.FaultDetail? What's the namespace? In what assembly?

To make this happen in .NET, we have to introduce something called a "fault contract". As you recall from the previous document, WCF has service contracts and operation contracts. Fault contracts are just another contract type in the contact family.

These are setup by applying the System.ServiceModel.FaultContractAttribute attribute to various operations of your service contract.  When you apply this attribute, you must tell it what type you would like to allow to be thrown from that specific operation.  This is simply done by giving the constructor of the fault contract attribute to type object of your fault detail type.  For example, below is our operation contract with the fault contract applied.

//- GetPersonData -//
[OperationContract]
[FaultContract(typeof(FaultDetail))]
Person GetPersonData(String personGuid);

If you're following along and paying close attention you should be thinking "How in the WORLD does that help the client? This is on the server! The same SOAP data is going to come over the wire and the client has no more information." Well, as you recall from the previous document, the contracts must be both on the service-side and on the client-side. In the case of .NET, these are the same types since the contracts are in an assembly shared by both client and service (remember, use of the "Add Service Reference" for .NET-to-.NET communication provides ZERO value and only complicates life).

So, if you are doing .NET-to-.NET, your client contract DOES have this and WCF on the client will automatically know to use that specific type when deserializing the “detail” part of the fault SOAP message.  Let's see this in action.

First, let's review our previous setup:

//+ basicHttpBinding
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");

This is all that's required to make a .NET-to-.NET WCF call. Setup a address-binding-contract combination to create a channel, then call the operation through the channel. Not a big deal. Now let's add one level of fault handing:

//+ basicHttpBinding
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
try
{
    Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException ex)
{
    //+ without fault contract     
    WriteToOutput("There was an error...(FaultException)");
    //+ this is the message from “faultstring” in the SOAP message     
    WriteToOutput(ex.Message);
}

This example shows handling a fault exception without having the first clue what type is being sent. We can, however, access the fault message by accessing Message property of the fault.  So, in this case, “ex.Message” will contain “Invalid guid.”.  Now let’s go one step further:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
try
{
    Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException<FaultDetail> ex)
{
    WriteToOutput("There was an error...(FaultException<FaultDetail>");
    //+
    FaultDetail detail = ex.Detail;
    WriteToOutput("ErrorCode: " + detail.ErrorCode.ToString());
    WriteToOutput("Type: " + detail.Type);
    //+ again, this is the message from “faultstring” in the SOAP message
    WriteToOutput(ex.Message);
}
catch (FaultException ex)
{
    WriteToOutput("There was an error...(FaultException)");
    WriteToOutput(ex.Message);
}

In this example, we are taking advantage of the fault contract on the client operation.  Notice that we have access to the  actual detail content that was sent over the wire.  Not only that, but we can access it as a true type via the Detail property of our generic fault exception. This makes things a lot easier.

Remember, the only difference these two examples is the presence of the fault contract on the client operation. If the fault contract were NOT on the client operation, then the "FaultException" catch-block would be caught, not the generic one.

Throwing Exceptions (Bad!)

At this point, you should be able to see that the original fault SOAP message I showed you involving the InvalidOperationException is, in fact, not entirely fictional. It is possible to send an exception over the wire. All you would need to do is something like this (in addition to setting up a fault contract on the client operation):

String message = "Invalid guid.";
throw new FaultException<InvalidOperationException>(new InvalidOperationException(message), message);

Having said this, throwing an exception over the wire is very poor form. It's not as bad as publicly exposing a private field, using the "var" C# keyword for non-anonymous types, or camelCasing() .NET method names, but it's still viewed as a very poor practice. Why? Well, you tell me. Take a look at the following two examples:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Really descriptive message here.</faultstring>
      <detail>
        <InvalidOperationException xmlns="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
          <ClassName i:type="x:string" xmlns="">System.InvalidOperationException</ClassName>
          <Message i:type="x:string" xmlns="">Really descriptive message here.</Message>
          <Data i:nil="true" xmlns=""/>
          <InnerException i:nil="true" xmlns=""/>
          <HelpURL i:nil="true" xmlns=""/>
          <StackTraceString i:nil="true" xmlns=""/>
          <RemoteStackTraceString i:nil="true" xmlns=""/>
          <RemoteStackIndex i:type="x:int" xmlns="">0</RemoteStackIndex>
          <ExceptionMethod i:nil="true" xmlns=""/>
          <HResult i:type="x:int" xmlns="">-2146233079</HResult>
          <Source i:nil="true" xmlns=""/>
        </InvalidOperationException>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

... and ... 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Notice that the first example (the exception) has many items going over the wire that are never even used, thus wasting serialization and deserialization processing time as well as bandwidth, not to mention making the SOAP message more difficult to read. Notice also that each of the elements in the second example (the fault detail) relate to the task at hand. Therefore, you should always define a fault detail type when dealing with fault exceptions.

Applying to Silverlight

Everything we discussed so far relating to the service applies to Silverlight. That is, you may use the same service for both Silverlight and .NET.  However, if you would like to use the strongly typed fault details in Silverlight as we discussed in .NET, then you need to apply the fault contract attribute to the Silverlight async operation (note: technically this has nothing to do with Silverlight; if you are using async calls in .NET, then Silverlight and .NET will share those).  More specifically, the "Begin" method of your operation contract. Here's an example:

//- BeginGetPersonData -//
[OperationContract(AsyncPattern = true)]
[FaultContract(typeof(FaultDetail))]
IAsyncResult BeginGetPersonData(String personGuid, AsyncCallback callback, Object state);

Note also that since Silverlight is NOT .NET, you have to get the fault detail from the .NET world over to the Silverlight world.  Now, given that nothing about the type is different in the .NET and Silverlight worlds, you can easily share it between the two.  On way to do this is by using the “Add As Link” feature in Visual Studio.  More more ways of sharing types and assemblies between .NET and Silverlight see my document entitled Reusing .NET Assemblies in Silverlight.

Now given this setup, you can upgrade your service access by wrapping your call to the "End" method in a try/catch block.

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    try { Person person = ((IPersonService)result.AsyncState).EndGetPersonData(result); Write(person.FirstName); }
    catch (FaultException<FaultDetail>)
    {
        Write("There was an error...(FaultException<FaultDetail)");
    }
    catch (FaultException)
    {
        Write("There was an error...(FaultException)");
    }
    catch (Exception)
    {
        Write("There was an error...(Exception)");
    }
};

When you run this, barring any other problems, you can expect that the FaultException<FaultDetail> catch block be called, since that's what's going on the .NET side.  Everything will work the same from here on out.  In fact, if you are doing async calls in the .NET world, your code won’t have any differences at all.

Service Modification for Silverlight

Notice that when I said that the FaultException<FaultDetail> catch block would be called, I said “barring any other problems”.  This is a very important little phrase.  In fact, if you did actually try to run the above example, you would see something rather shocking: the FaultException<FaultDetail> block was NOT hit.  Instead, the Exception block was.  At this point, if you are confused... then you’re probably following along just fine.

Thus, you begin debugging. First, you check the exception message (ex.Message). It says "The remote server returned an error: NotFound.". What? Whatever. Then you realize that you need to see what WCF sent back. So, you open fiddler and rerun the example. You see the following:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Well, that's correct. WCF is sending the correct data back. At this point, you go to the next step of debugging by proceeding to bang you head against a wall.

What's the problem?

Here it is: Silverlight a browser plugin. Therefore, Silverlight must obey the rules of plugins and are also limited to the information given to them by their host browser. In the case of fault exceptions, faults are send over an HTTP connect with a non-200 HTTP status code. This makes sense since 200 means “OK” and fault means “not-OK”. Browsers do not send this kind of information to plugins. Thus, not Microsoft’s fault (so, stop cursing them—redirect any and all of that to the IE team). Once we see this truth about the internal mechanics, we can see a glimpse of hope.

How so? Well, the problem clearly has nothing to do with faults. It has to do with the HTTP non-200 status code. Therefore, in order for Silverlight to see the fault exception we need to make sure the service with which the Silverlight client is communicating sends a 200 HTTP status code at all times, regardless of a success or not. This is incredibly easy in WCF using a concept known as an ErrorHandler.

ErrorHandlers are classes which implement the System.ServiceModel.Dispatcher.IErrorHandler interface. One of the required methods that this interface requires for you to implement has the following signature:

void ProvideFault(Exception error, MessageVersion version, ref Message fault)

By implementing this method and registering the ErrorHandler to WCF, you can effectively change the HTTP status code. Below is one implementation of this (notice that name is HttpStatusCode200ErrorHandler not SilverlightErrorHandler-- this can be used for anything that doesn't support non-HTTP 200 codes):

#region Copyright
//+ Themelia Pro 2.0 - Core Module
//+ Copyright © Jampad Technology, Inc. 2007-2009
#endregion
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
//+
namespace Themelia.ServiceModel.Behavior
{
    /// <summary>
    /// Sets the HTTP code to 200 for faults.
    /// </summary>
    public class HttpStatusCode200ErrorHandler : IErrorHandler
    {
        //- @ServiceType -//
        public Type ServiceType { get; set; }

        //+
        //- @Ctor -//
        public HttpStatusCode200ErrorHandler(Type serviceType)
        {
            ServiceType = serviceType;
        }

        //+
        //- @HandleError -//
        public bool HandleError(Exception error)
        {
            return false;
        }

        //- @ProvideFault -//
        public virtual void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            fault.Properties[HttpResponseMessageProperty.Name] = new HttpResponseMessageProperty
            {
                StatusCode = System.Net.HttpStatusCode.OK
            };
        }
    }
}

As you can see, on the created fault there is a Properties bag. By adding our own HttpResponseMessageProperty to this bag under the name of HttpResponseMessageProperty.Name, we can effectively change the HTTP status code.

To install an error handler, just create a service behavior.  A service behavior is much like an operation behavior, but, as you may have guessed, is for a service.  These are really just classes that implement the System.ServiceModel.Description.IServiceBehavior interface.  In our case, all we care about is using the ApplyDispatchBehavior method to install our error handler (this should all sound very familiar since we did something very analogous with an operation behavior and invoker earlier.)  Here’s a sample behavior to install the error handler:

#region Copyright
//+ Themelia Pro 2.0 - Core Module
//+ Copyright © Jampad Technology, Inc. 2007-2009
#endregion
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
//+
namespace Themelia.ServiceModel.Behavior
{
    /// <summary>
    /// Applies HttpStatusCode200ErrorHandler.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class HttpStatusCode200Behavior : Attribute, IServiceBehavior
    {
        //- @AddBindingParameters -//
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            //+ blank
        }

        //- @ApplyDispatchBehavior -//
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(new HttpStatusCode200ErrorHandler(serviceDescription.ServiceType));
            }
        }

        //- @Validate -//
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            //+ blank
        }
    }
}

Now we just need to install the behavior. You can do this in a number of different ways, but I almost always use the service host factory approach.

The purpose behind one of these is to create a service host, which in turn hosts... (drum roll, please)... a service.  As with most WCF features, these are very powerful.  We use them to do all kinds of programmatic service alterations.  For example, we can add custom endpoints, setup metadata, apply more security, or, in our case, install a service behavior (which, in turn, installs our error handler).

A service host factory is simply a class which inherits from System.ServiceModel.Activation.ServiceHostFactory.  To create our service host factory , we are going override the following signature of a newly created service host factory:

ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

In this method, we are going to create our service host, add our behavior to that host, then return it. Here's the end result:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
//+
namespace Contact.Service.Activation
{
    public class PersonServiceHostFactory : WebServiceHostFactory
    {
        //- @CreateServiceHost -//
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = new ServiceHost(serviceType, baseAddresses);
            //+ HTTP 200
            host.Description.Behaviors.Add(new Themelia.ServiceModel.Behavior.HttpStatusCode200Behavior());
            //+
            return host;
        }
    }
}

Now, we just need our service host to use this factory. Your service host in the context of the web is the /SOMETHING.svc file. All we need to do is open this file and set the service directive "Factory" property to the name of our factory. For example:

<%@ ServiceHost Service="Contact.Service.PersonService" Factory="Contact.Service.Activation.PersonServiceHostFactory" %>

Now we are done.  When your access this service, the service host factory will create the host and add the error handler.  Then, when any error occurs,t he error handler will catch the error and set the HTTP status code to 200.  Thus, the browser will send the fault message to Silverlight and we’ll finally see that the correct FaultException<FaultDetail> catch block is hit.

Conclusion

In sum, WCF provides a very straight-forward, easy to implement fault management solution, which retains the idioms of C# and the purity of the SOAP standard. Not only that, but with a simple flip of a switch Silverlight works flawlessly with the feature that WCF has had since its first release.

Faults are really nothing more than SOAP messages of a certain format.  If there is an error, WCF is smart enough to not just serialize some exception, but, instead, send a fault SOAP message over the wire.  Thus, making the entire error handling process end-to-end very streamlined.

Whereas Silverlight 2 requires some extra massaging in order to get fault contracts implemented, Silverlight 3 has the feature built right in. Using the techniques described in this document, Silverlight 3 developers should be able to keep with the streamlined nature of WCF without the need for any custom fault management.

Samples for this document may be found here.

New Silverlight 3 Features

Though I’m a member of the Silverlight 3 Early Adopter’s Program (and thus have been getting weekly builds of Silverlight long before the public beta), I’m probably not going to be writing anything about the new features.  This isn’t because Silverlight 3 is boring, but, rather, because I have a strict policy of never doing something that other’s are already doing.  So, I would like to direct your attention to a few web sites showing the awesome provided by Silverlight 3 (and you won’t find business-application boringness here).

First, Tim Huerer has a nice post giving a very quick rundown of the new features:

Second, Jeff Prosise’s blog shows some of the cooler features of Silverlight 3.  Maybe it’s just because I absolutely HATE business application development, but I find Jeff’s blog to be 100x more interesting than the “how to write use X to write your boring line-of-business application.”  His work is also not for the naive or faint of heart.  Instead, it’s for professional developers (i.e. the extremely rare people who aren’t afraid to do things the right way.)  If Jeff adds more stuff, I’ll add them to this list.

Finally, you can always head over to the Mix ‘09 web site and watch some Silverlight 3 (and 2) videos.  Most of them also have PowerPoint files associated with them.  Personally, I can’t stand the torture of listening to someone take 30 minutes to say something that I can ready in 3 minutes.  That’s one reason I turned Microsoft down when they asked me to turn my Understanding WCF Services in Silverlight 2 into a talk at Mix.  Boring.  Here’s the Mix link:

Jeff-Prosise's-Silverlight-Tips

This post may be completely meaningless to most of the developers out there as it deals with my type of development: non-business application development.  More specifically, Jeff Prosise of Wintellect (the Navy SEALs of .NET) has posted a few really nice tips and tricks for Silverlight development.  These are really great tricks that serve as great examples of some of the more powerful things you can do with Silverlight:

Links

Exception Handlers for Silverlight 2.0

Whereas Themelia is my foundation for all .NET development, it’s a little known fact that I have an internal build of it specifically used for Silverlight.  Among the many features of Themelia for Silverlight (hereafter called “ThemeliaSL”) is something I call Exception Handlers.  This isn’t the same thing as the “catch” block of a try/catch.  No, it’s a concept specific to Silverlight.  Also, this is a fairly discrete feature that you can implement in your own Silverlight applications without the need of my full framework.  However, before you can understand this feature, you need to understand Silverlight currently works with unhandled exceptions.

When Silverlight throws an exception that’s unhandled, it eventually gets bubbled up to your System.Windows.Application instance.  If you are handling the UnhandledException event of this class, then you have an opportunity to handle this exception on your own.  When your UnhandledException event handler is called, you are passed an instance of System.Windows.ApplicationUnhandledExceptionEventArgs.  In this class you are provided a property named ExceptionObject of type System.Exception which holds the actual exception object that has been thrown.  There’s one other property though: Handled.  This property is a boolean which provides you with the ability to say whether you handled the exception or not.  If you set this property to true, then you are telling Silverlight that the problem has been taken care of.  If you set it to false, then you are telling Silverlight that it’s about to die.

That’s really all there is to Silverlight exception handling.  You can, however, make things a bit more streamlined.  Say, for example, you know of various types of exceptions that your application or underlying frameworks will throw.  You also know that you want to handle some of them in a specific way.  Or maybe, you just don’t want any communications exceptions to ever be sent back to the client.  For situations like these, you can use the concept I refer to as exception handlers.

Before we implement this concept, lets see how it will be used first:

public class Application : Themelia.Windows.Application
{
    public Application()
        : base()
    {
        AddExceptionHandler(typeof(CommunicationException), delegate(Exception ex)
        {
            if (ex.InnerException == null)
            {

                ReportExceptionToFirebug(ex.InnerException);
                return true;
            }
            //+ 
            return false;
        });
    }
}

Essentially, call the base constructor of the Application class we are about to create.  Then, for each exception that you want to handle, register it with the AddExceptionHandler method, sending it the type of the exception and a delegate of type Func<Exception, Boolean>.  In this example, when an unhandled exception of type CommunicationException is thrown, we automatically check to see if it has an inner exception.  If so, we report the exception in a special way and mark the exception as handled.

You could also add more exception handlers.  Here’s another example:

AddExceptionHandler(typeof(ArgumentException), delegate(Exception ex)
{
    ReportValidationError(ex);
    return true;
});

While this example is a rather silly one (because validation shouldn’t throw exceptions!), it does go to show you this is essentially a declarative model for exception handling.  Now it’s time to move on to build the thing.

First, create your own abstract version of System.Windows.Application.  This is typically a good idea anyways.  It allows you to control your applications in a very streamlined manner.  In this class, add the following static member:

private static Dictionary<Type, Func<Exception, Boolean>> HandlerRegistry = new Dictionary<Type, Func<Exception, Boolean>>();

This represents a registry of all exceptions handlers registered to your application.  It’s a dictionary with the key representing the Type of the exception and the value representing a delegate to be called when that exception is raised.

You’ll also need a standard .NET locking object:

private static Object _lock = new Object(); 

Now add the following method:

//- #AddExceptionHandler -// 
protected void AddExceptionHandler(Type type, Func<Exception, Boolean> handler)
{
    lock (_lock)
    {
        HandlerRegistry.Add(type, handler);
    }
}

This will allow you to register exception handlers from your concrete instance of your custom application class.

Now it’s on to the meat of the implementation.  In your base class application class constructor, handle the UnhandledException event.

this.UnhandledException += new EventHandler<System.Windows.ApplicationUnhandledExceptionEventArgs>(OnUnhandledException);

Then, in the method that will be called upon the event being raised, do something like this:

//- #OnUnhandledException -// 
protected virtual void OnUnhandledException(Object sender, ApplicationUnhandledExceptionEventArgs ea)
{
    lock (_lock)
    {
        if (HandlerRegistry.Count > 0)
        {
            Exception exception = ea.ExceptionObject;
            Type type = exception.GetType();
            if (HandlerRegistry.ContainsKey(type))
            {
                ea.Handled = HandlerRegistry[type](exception);
            }
        }
    }
    if (!System.Diagnostics.Debugger.IsAttached && this.AutoReportErrorToDOM && !ea.Handled)
    {
        ea.Handled = true;
        Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(ea); });
    }
} 

Essentially, if there are any registered handlers, check to see if the currently thrown exception is one of those exception registered to be handled.  If so, then pull the delegate from the registry and call it.

Notice that the delegate that we registered is Func<Exception, Boolean>.  Functionally, this means is that the delegate will accept an Exception object and return a boolean.  Interpreted, this means that in the delegate you register you need to return a boolean representing whether you want the exception handled or not.

You may also notice in the above code that there is a property named AutoReportErrorToDOM.  This does exactly what it says  and it’s nothing too exciting:

//- @AutoReportErrorToDOM -// 
public Boolean AutoReportErrorToDOM { get; set; }

The ReportErrorToDOM method is the same one that Visual Studio 2008 throws in with the Silverlight template.  For completeness, here it is:

//- #ReportErrorToDOM -// 
protected void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs ea)
{
    try
    {
        String errorMsg = ea.ExceptionObject.Message + ea.ExceptionObject.StackTrace;
        errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
        System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg + "\");");
    }
    catch (Exception)
    {
    }
}

At this point, you have everything you need to make the samples that we went through work properly.  Just be sure to base your application class on the new one and you’ll be set.

One important note is that when you are using custom visual entities in Silverlight, you need to make sure that you properly register the namespace in XAML.  For example, say the above class was called “Application” in the “Themelia.Windows” CLR namespace in the “Themelia.Silverlight” assembly.  For this configuration, you would use the following xaml:

<t:Application 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:t="clr-namespace:Themelia.Windows;assembly=Themelia.Silverlight" 
    x:Class="Sample.Application" />

With this, you’re all set.

Tip: Quick Reflector Loading for .NET and Silverlight

In my daily development there are three tools that I keep open almost constantly:  Visual Studio 2008, Windows Debugger, and Reflector.  The first is obvious, the second is for extreme-debugging, and the third so I can have a clue what I’m working with (...I have NO idea how people do .NET or Silverlight development without reflector!)  The first two I access with icons, while the third is one that I open and close at least 10 times a day.

To quickly access reflector (as well as Notepad2 and a whole host of sysinternals apps!) I throw it in my Windows folder so I can access it from the Run box.  Not only that, but I typically rename tools I throw in there to have only one letter.  Reflector is “r”.  So, I hit Win-R and type “r”.  Up comes reflector.  Here’s the thing though: I work in both .NET and Silverlight equally.  Yet, Reflector only loads ONE of them.  What to do?

The fix is simple: copy r.exe to rs.exe.  When I load r.exe, I select .NET.  When I load rs.exe, I select Silverlight.  Now I when I hit Win-R, I can type either “r” or “rs” depending on what framework I want to inspect.  You could even take the concept further by making a “rf.exe” for the compact framework”  Each “x.exe” will have it’s own “x.cfg” so the configurations won’t bleed over each other.

1 2 3 4 5

Powered by
Python / Django / Elasticsearch / Azure / Nginx / CentOS 7

Mini-icons are part of the Silk Icons set of icons at famfamfam.com