WCF自定义错误处理程序有条件地返回xml或json?

时间:2013-02-21 17:02:11

标签: wcf ierrorhandler iservicebehaviors

open311协议需要支持以下格式的端点:

  • domain / requests.xml
  • 域/ requests.json

第一个端点接受xml请求,第二个json请求。

协议进一步指定应以请求格式(xml或json)返回错误。

实现ServiceBehaviorErrorHandler时,我发现无法确定ProvideFault方法中的请求格式(xml或json)。所有示例都返回json xml。

如何确定请求格式,以便以相同的格式返回错误消息?我的实施:

    /// <summary>
/// From http://www.codeproject.com/Articles/43621/Extending-WCF-Part-I
/// </summary>
public class ExtendedServiceErrorHandler : IErrorHandler, IServiceBehavior
{
    #region IErrorHandler Members

    bool IErrorHandler.HandleError( Exception error )
    {
        return ( error is Open311Exception );
    }

    /*
     * TODO: HTTP error codes are required, but the code in the response body shouldn't necessarily match the HTTP error code, 
     * so that more specific and unique error code identifiers can be used. 
     * The HTTP error codes should always be 404 for resources that don't exist, 
     * 403 for errors because of wrong or missing api_key and basically 
     * 400 for any other error where the request can not be fulfilled as expected. 
     * Multiple errors codes and descriptions can be returned in the body (the response is an array).
     */
    void IErrorHandler.ProvideFault( Exception error, MessageVersion version, ref Message fault )
    {
        var ajaxErrors = new AjaxErrors();
        var open311Error = error as Open311Exception;
        if( null != open311Error )
        {
            ajaxErrors.Add( new AjaxError()
                {
                    Code = open311Error.Code,
                    Message = open311Error.Message
                } );
        }
        else
        {
            ajaxErrors.Add( new AjaxError()
                {
                    Code = 400,
                    Message = error.Message
                } );
        }
        var contentType = "application/json"; // TODO: how do we know?
        // WebOperationContext.Current.IncomingRequest.ContentType doesn't work
        WebContentFormat webContentFormat;
        switch( contentType )
        {
            case "application/json":
                fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractJsonSerializer( ajaxErrors.GetType() ) );
                webContentFormat = WebContentFormat.Json;
                break;
            case "application/xml":
                fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractSerializer( ajaxErrors.GetType() ) );
                webContentFormat = WebContentFormat.Xml;
                break;
            default:
                fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractSerializer( ajaxErrors.GetType() ) );
                webContentFormat = WebContentFormat.Raw;
                break;
        }
        var wbf = new WebBodyFormatMessageProperty( webContentFormat );
        fault.Properties.Add( WebBodyFormatMessageProperty.Name, wbf );
        WebOperationContext.Current.OutgoingResponse.ContentType = contentType;
        WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK; //  HttpStatusCode.BadRequest;
    }

    #endregion

    #region IServiceBehavior Members

    void IServiceBehavior.AddBindingParameters( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters )
    {
        // nothing to do?
    }

    void IServiceBehavior.ApplyDispatchBehavior( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase )
    {
        var errorHandler = new ExtendedServiceErrorHandler();

        foreach( ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers )
        {
            channelDispatcher.ErrorHandlers.Add( errorHandler );
        }
    }

    void IServiceBehavior.Validate( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase )
    {
        // nothing to do?
    }

    #endregion
}

1 个答案:

答案 0 :(得分:2)

这就是你所寻找的我相信:http://msdn.microsoft.com/en-us/library/vstudio/ee513227(v=vs.100).aspx

  

Windows Communication Foundation(WCF)Web HTTP错误   处理使您可以从WCF Web HTTP服务返回错误   指定HTTP状态代码并使用相同的方式返回错误详细信息   格式化为操作(例如,XML或JSON)。