IErrorHandler дает страницу не найдена для ответа Json в остальных - PullRequest
0 голосов
/ 21 сентября 2011

Для любого исключения веб-протокола обработчик ошибок должен обработать исключение и дать только ответ json, а страница не найдена.

Вот конфигурация для услуги

    <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <extensions>
        <behaviorExtensions>
          <add name="enhancedWebHttp" type="Licensing.Services.EnhancedWebHttpElement, Licensing.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </behaviorExtensions>
      </extensions>
      <bindings>
        <webHttpBinding>
          <binding name="webBinding">
          </binding>
        </webHttpBinding>
      </bindings>
      <behaviors>
        <endpointBehaviors>
          <behavior name="jsonBehavior">
            <enhancedWebHttp defaultOutgoingResponseFormat="Json"/>
          </behavior>
          <behavior name="poxBehavior">
            <enhancedWebHttp/>
          </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
          <behavior name="Licensing.Services.restserviceBehavior" >
            <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
            <serviceMetadata httpGetEnabled="true"/>
            <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
            <serviceDebug includeExceptionDetailInFaults="false"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
      <services>
        <service name="Licensing.Services.restservice" behaviorConfiguration="Licensing.Services.restserviceBehavior">
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost/LicensingAPIService/restservice.svc"/>
            </baseAddresses>
          </host>
          <endpoint address="json" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="jsonBehavior"
          contract="Licensing.Services.IRestService" />
          <endpoint address="pox" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="poxBehavior"
          contract="Licensing.Services.IRestService"/>
        </service>
      </services>
    </system.serviceModel>

Вот код для улучшенного WebHttp

public sealed class EnhancedWebHttpElement : BehaviorExtensionElement
{
    #region Type specific properties

    [ConfigurationProperty("defaultBodyStyle", DefaultValue = WebMessageBodyStyle.Bare)]
    public WebMessageBodyStyle DefaultBodyStyle
    {
        get
        {
            return (WebMessageBodyStyle)this["defaultBodyStyle"];
        }

        set
        {
            this["defaultBodyStyle"] = value;
        }
    }

    [ConfigurationProperty("defaultOutgoingRequestFormat", DefaultValue = WebMessageFormat.Xml)]
    public WebMessageFormat DefaultOutgoingRequestFormat
    {
        get
        {
            return (WebMessageFormat)this["defaultOutgoingRequestFormat"];
        }

        set
        {
            this["defaultOutgoingRequestFormat"] = value;
        }
    }

    [ConfigurationProperty("defaultOutgoingResponseFormat", DefaultValue = WebMessageFormat.Xml)]
    public WebMessageFormat DefaultOutgoingResponseFormat
    {
        get
        {
            return (WebMessageFormat)this["defaultOutgoingResponseFormat"];
        }

        set
        {
            this["defaultOutgoingResponseFormat"] = value;
        }
    }

    #endregion

    #region Base class overrides

    protected override object CreateBehavior()
    {
        LicensingBehavior result = new LicensingBehavior();

        result.DefaultBodyStyle = this.DefaultBodyStyle;
        result.DefaultOutgoingRequestFormat = this.DefaultOutgoingRequestFormat;
        result.DefaultOutgoingResponseFormat = this.DefaultOutgoingResponseFormat;
        return result;
    }

    public override Type BehaviorType
    {
        get
        {
            return typeof(LicensingBehavior);
        }
    }

    #endregion
} 

Вот код для лицензионного поведения

public class LicensingBehavior : WebHttpBehavior
{

    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        int errorHandlerCount = endpointDispatcher.ChannelDispatcher.ErrorHandlers.Count;
        base.AddServerErrorHandlers(endpoint, endpointDispatcher);
        IErrorHandler webHttpErrorHandler = endpointDispatcher.ChannelDispatcher.ErrorHandlers[errorHandlerCount];
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.RemoveAt(errorHandlerCount);
        RestErrorHandler newHandler = new RestErrorHandler(webHttpErrorHandler,DefaultOutgoingResponseFormat);
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(newHandler);
    }        

}

Вот код для ErrorHandler.

public class RestErrorHandler : IErrorHandler
{
    IErrorHandler _originalErrorHandler;
    WebMessageFormat _format;
    public RestErrorHandler(IErrorHandler originalErrorHandler,WebMessageFormat format)
    {
        this._originalErrorHandler = originalErrorHandler;
        this._format = format;
    }

    public bool HandleError(Exception error)
    {
        return error is WebProtocolException;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        WebProtocolException licensingException = error as WebProtocolException;
        if (licensingException != null)
        {

            fault = Message.CreateMessage(version, null, new ValidationErrorBodyWriter(licensingException));
            if (_format == WebMessageFormat.Json)
            {
                HttpResponseMessageProperty prop = new HttpResponseMessageProperty();
                prop.StatusCode = licensingException.StatusCode;
                prop.Headers[HttpResponseHeader.ContentType] = "application/json; charset=utf-8";
                fault.Properties.Add(HttpResponseMessageProperty.Name, prop);
                fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));
            }
            else if(_format == WebMessageFormat.Xml)
            {
                HttpResponseMessageProperty prop = new HttpResponseMessageProperty();
                prop.StatusCode = licensingException.StatusCode;
                prop.Headers[HttpResponseHeader.ContentType] = "application/xml; charset=utf-8";
                fault.Properties.Add(HttpResponseMessageProperty.Name, prop);
                fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Xml));
            }
        }
        else
        {
            this._originalErrorHandler.ProvideFault(error, version, ref fault);
        }
    }

    class ValidationErrorBodyWriter : BodyWriter
    {
        private WebProtocolException validationException;
        Encoding utf8Encoding = new UTF8Encoding(false);

        public ValidationErrorBodyWriter(WebProtocolException validationException)
            : base(true)
        {
            this.validationException = validationException;
        }

        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("root");
            writer.WriteAttributeString("type", "object");

            writer.WriteStartElement("StatusCode");
            writer.WriteAttributeString("type", "string");
            writer.WriteString(this.validationException.StatusCode.ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("Description");
            writer.WriteAttributeString("type", "string");
            writer.WriteString(this.validationException.StatusDescription);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
}

1 Ответ

0 голосов
/ 22 сентября 2011

Я создал пустой проект ASP.NET, скопировал в него точный код (изменил некоторые пространства имен, ничего не должно повлиять на результат), и он сработал просто отлично - в конечной точке "json" исключение WebProtocolException возвращается в формате JSON, тогда как в конечной точке «pox» то же исключение возвращается в формате XML. Вы можете загрузить проект (называемый SO_7498771.zip) из https://skydrive.live.com/?cid=99984bbbec66d789&sc=documents&uc=1&id=99984BBBEC66D789%21944#, и сравнить его с вашей реализацией, чтобы увидеть, есть ли что-то другое.

...