Causing HTTP error status to be returned in WCF

2019-03-21 06:58发布

问题:

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.

回答1:

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.



回答2:

If you are using standard WCF then FaultException is the correct approach to this. If you do not wish to do that and you want to be RESTful then you should use the REST WCF approach (Here is a quick start template for 4.0 and for 3.5). This fully supports returning HTTP Status Codes to the client.



回答3:

I wanted to implement the same solution you are asking, the link below worked perfect when you want to play with HTTP status codes.

How can I return a custom HTTP status code from a WCF REST method?

There is a WebOperationContext that you can access and it has a OutgoingResponse property of type OutgoingWebResponseContext which has a StatusCode property that can be set.

WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;