Causing HTTP error status to be returned in WCF

2019-03-21 06:31发布

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.

3条回答
可以哭但决不认输i
2楼-- · 2019-03-21 06:58

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;
查看更多
再贱就再见
3楼-- · 2019-03-21 07:05

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.

查看更多
祖国的老花朵
4楼-- · 2019-03-21 07:06

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.

查看更多
登录 后发表回答