This post is part of a series about WCF extensibility points. For a list of all previous posts and planned future ones, go to the index page.
Whenever an operation throws an (unhandled) exception, the WCF runtime will catch that exception to prevent the whole service from going down. In most of the cases, that would mean a generic response being returned to the service (such as HTTP 500 Internal Server Error). If the exception happens to be a FaultException, or if the service has the debug setting to include exception detail in faults enabled (either using ServiceBehaviorAttribute.IncludeExceptionDetailInFaults or using the config setting in the <serviceDebug> element), then the response will contain a SOAP fault with the information in the exception. This works fine for most services, but there are cases where the application wants to customize the error which is returned to the client.
None. As with most runtime extensibility points, there are no public implementations in WCF. There are some internal implementations, mostly on the Web HTTP support (to be able to send errors back to the client in a format more REST / browser-friendly than SOAP).
When an unhandled exception bubbles up from a service operation, ProvideFault is called for all error handlers registered in the list of handlers of the channel dispatcher (except for some “fatal” exceptions, such as stack overflows, out of memory, etc., in which case the service will be terminated). Each one will have the opportunity of inspecting the exception, and creating / modifying the “fault” to be returned to the client. The parameter name is actually misleading, since the message does not need to be a fault message. The MSDN documentation is misleading as well, as it says that it “enables the creation of a custom FaultException<TDetail> that is returned from an exception”. The returned “fault” can be any Message object, and it will be encoded and sent to the client as any other messages would.
HandleError is called after the message was returned to the client, and it’s used mostly for logging, notification and possibly shutting down the application. It’s also used to control whether a session in the server (if there is one) is to be terminated: if any of the error handlers returns true, then the exception is considered to be “contained”, and the session will be kept alive; if all error handlers return false (or if there is no custom error handler registered for the dispatcher) then the session is aborted. The instance context for the service is also aborted, if it’s not Single, if no error handlers can handle a given exception.
Error handlers only apply at the server side, and they are associated with the channel dispatchers. They’re typically defined in either service behaviors (for global error handling) or endpoint behaviors (for controlling the error response format for a specific endpoint type, such as web endpoints), as shown in the example below.
I’ve seen quite a few of services where the first thing that each operation does is to validate that the input parameters have valid properties. A zip code has to follow certain regular expression, the balance a bank account should not be negative (at least in most banks), someone’s age should not be negative, etc. There is a great library for annotating class properties in the System.ComponentModel.DataAnnotations namespace, and it’s fairly simple to implement a simple validation using a parameter inspector for all the operations in the contract. In this example I have a simple HTML form application, and I’ll use an error handler to return the validation information in format which is easily accessible by the browser (i.e., in JSON).
And before starting with the code, the usual disclaimer: this is a sample for illustrating the topic of this post, this is not production-ready code. I tested it for a few contracts and it worked, but I cannot guarantee that it will work for all scenarios (please let me know if you find a bug or something missing). A more complete implementation would also include validation for simple types (which this one doesn’t), and it would definitely *not* use an in-memory dictionary as the “database” for storing the data. Also, the validation doesn’t go deep in the objects by default, so it currently it only validates the members of the parameters (not the members of the members).
I’ll start with the service. It’s a simple contact manager, where we can add, delete and query contacts
The Contact class is defined with some annotation for its data members. Both name and e-mail properties are required (i.e., they cannot be null), and their values must follow certain guidelines. The age is not required, but it’s limited to a certain range.
Now to add the validation logic. Since this is a web endpoint, I’ll create a subclass of WebHttpBehavior which has some nice overrides I can use for that. The behavior must add two elements: a parameter inspector which will validate the incoming data, and the new error handler which will return the errors in a nice format.
The inspector is fairly simple, it simply calls the Validator.ValidateObject on every non-null parameter which is passed to the function. This will scan the data annotation properties and validate the instance against them.
The error handler is the piece responsible for sending the validation error in a form that the client understands. In this implementation, it creates a new message object if the exception is a ValidationException (which is thrown when the ValidateObject call fails). If the exception is something else, it will simply delegate to the original error handler added by the WebHttpBehavior. The new message created for validation errors will use the Json encoder from the WebMessageEncodingBindingElement (guided by the WebBodyFormatMessageProperty in the message). And the body of the message is written using the mapping between XML and JSON to create the expected output.
The service itself is done. In order to hook up the endpoint behavior to the service creation, I’m using a custom service host factory (see more about it in the next post), so that I don’t need to worry about configuration extensions.
Now that everything is set up, we can test the service. I like to use a unit test framework (when I was writing this sample I wrote the tests first), and qUnit is one of my favorites. Below is a snippet of the tests which I used to verify the service code.
And that’s it. In the code for this post I added a simple HTML form which uses this service as well.
One of my personal favorites: service host factories, or how to do everything in IIS without ever needing configuration (web.config).
[Code in this post]
[Back to the index]