How can I get my WCF service to communicate errors in a RESTful manner?  Specifically, if the caller passes invalid query string parameters to my method, I'd like to have a 400 or 404 HTTP error returned to the user.  When I search for HTTP error status in relation to WCF, all I can find are pages where people are trying to resolve errors they're receiving.  I'd rather not just throw a FaultException, because that gets converted to a 500 error, which is not the correct status code.
I found a helpful article here: http://zamd.net/2008/07/08/error-handling-with-webhttpbinding-for-ajaxjson/. Based on that, this is what I came up with:
public class HttpErrorsAttribute : Attribute, IEndpointBehavior
{
    public void AddBindingParameters(
        ServiceEndpoint endpoint, 
        BindingParameterCollection bindingParameters)
    {
    }
    public void ApplyClientBehavior(
        ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }
    public void ApplyDispatchBehavior(
        ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        var handlers = endpointDispatcher.ChannelDispatcher.ErrorHandlers;
        handlers.Clear();
        handlers.Add(new HttpErrorHandler());
    }
    public void Validate(ServiceEndpoint endpoint)
    {
    }
    public class HttpErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return true;
        }
        public void ProvideFault(
            Exception error, MessageVersion version, ref Message fault)
        {
            HttpStatusCode status;
            if (error is HttpException)
            {
                var httpError = error as HttpException;
                status = (HttpStatusCode)httpError.GetHttpCode();
            }
            else if (error is ArgumentException)
            {
                status = HttpStatusCode.BadRequest;
            }
            else
            {
                status = HttpStatusCode.InternalServerError;
            }
            // return custom error code.
            fault = Message.CreateMessage(version, "", error.Message);
            fault.Properties.Add(
                HttpResponseMessageProperty.Name,
                new HttpResponseMessageProperty
                {
                    StatusCode = status,
                    StatusDescription = error.Message
                }
            );
        }
    }
}
This allows me to add a [HttpErrors] attribute to my service.  In my custom error handler, I can ensure that the HTTP status codes I'd like to send are sent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With