none
Using WebFaultException from IErrorHandler RRS feed

  • Question

  • If I derive all of my exceptions from WebFaultException, and throw them directly from my services, the StatusCode set in the WebFaultException gets passed to the client. I'd rather not have to do that, since I'd rather throw generic exceptions like NotImplementedException, from my code.

    I've set up an IErrorHandler, with the expectation that I'd be able to catch exceptions like NotImplementedException, and then just do the conversion to a WebFaultException there.

    My code looks like this:

    public class HTTPBindingErrorHandler: IErrorHandler
    {
        public void ProvideFault(Exception exception, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)
        {
            if (exception is NotImplementedException)
            {
                WebFaultException wfe = new WebFaultException(HttpStatusCode.NotImplemented);
                MessageFault mf = wfe.CreateMessageFault();
                fault = Message.CreateMessage(version, mf, wfe.Action);
            }
        }
    
        public bool HandleError(Exception exception)
        {
            return false;
        }
    }

    When stepping through, I see that I'm getting to the code in ProvideFault, but the Status returned to the client is 400, not 501. Additionally, the body is:

    <Fault
        xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
        <Code>
            <Value>Receiver</Value>
            <Subcode>
                <Value
                    xmlns:a="http://schemas.microsoft.com/2009/WebFault">a:NotImplemented
                </Value>
            </Subcode>
        </Code>
        <Reason>
            <Text xml:lang="en-US">Not Implemented</Text>
        </Reason>
    </Fault>
    1. Why isn't the correct status code being returned?
    2. Why isn't the body in json?

    Addition: I've tried the recommendation of setting AutomaticFormatSelectionEnabled = false to the webhttpbehavior, but it still does not work. I'm self hosting, but I don't think that should make the difference. Here is the code I use to set up the service:

    Uri newUri = new Uri(info.baseURI, info.Path);
    WebServiceHost host = new WebServiceHost(info.Type, newUri);
    WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.InheritedFromHost;
    
    
    ServiceEndpoint ep = host.AddServiceEndpoint(info.Interface, binding, newUri);
    ep.Behaviors.Add(new WebHttpBehavior() { 
        DefaultOutgoingResponseFormat = WebMessageFormat.Json, 
        DefaultBodyStyle = WebMessageBodyStyle.Wrapped,
        AutomaticFormatSelectionEnabled = false } );
    ep.Behaviors.Add(new WebHttpCors.CorsSupportBehavior());
    ep.Behaviors.Add(new HTTPBindingErrorBehavior());

    Friday, August 1, 2014 3:55 AM

Answers

  • The returning of Faults as XML and not JSON coupled with an erroneous HTTP Status Code using the WebHttpBinding is a well documented issue. Unfortunately, I could not find exactly why WCF behaves this way.

    The solution for .NET Framework 4.0 or later is rather simple. Just set up the endpoint behavior configuration like this:

    <behavior name="ExtendedJSONBehavior">
         <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped"
                                            automaticFormatSelectionEnabled="false"/>
    </behavior>

    The key to this is the AutomaticFormatSelectionEnabled property being set to false.

    If you are using an earlier version of the Framework then this solution is reported to work: http://iainjmitchell.com/blog/?p=142. I would post the source code as that is recommended on this site, but there is a lot of code that iainjmitchell wrote for the solution.


    Monday, August 4, 2014 5:38 AM

All replies

  • The returning of Faults as XML and not JSON coupled with an erroneous HTTP Status Code using the WebHttpBinding is a well documented issue. Unfortunately, I could not find exactly why WCF behaves this way.

    The solution for .NET Framework 4.0 or later is rather simple. Just set up the endpoint behavior configuration like this:

    <behavior name="ExtendedJSONBehavior">
         <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped"
                                            automaticFormatSelectionEnabled="false"/>
    </behavior>

    The key to this is the AutomaticFormatSelectionEnabled property being set to false.

    If you are using an earlier version of the Framework then this solution is reported to work: http://iainjmitchell.com/blog/?p=142. I would post the source code as that is recommended on this site, but there is a lot of code that iainjmitchell wrote for the solution.


    Monday, August 4, 2014 5:38 AM
  • Hi Benjamin,

    You could simply change the response message property. Simply attached following code snippet to your code:

    // Modify response var rmp = new HttpResponseMessageProperty { StatusCode = HttpStatusCode.NotImplemented, StatusDescription = "Bad Request", }; rmp.Headers[HttpResponseHeader.ContentType] = "application/json"; // You can change your content type. fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);

    WebOperationContext ctx = WebOperationContext.Current;
    
    ctx.OutgoingResponse.StatusCode = HttpStatusCode.NotImplemented;

    Thanks,

    Maitrey


    • Edited by maitrey684 Thursday, January 21, 2016 1:54 PM Setting up outgoing response
    Thursday, January 21, 2016 1:51 PM