IErrorHandler 在休息时给出未找到 Json 响应的页面
对于任何 Web 协议异常,错误处理程序应处理该异常并仅给出 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>
这是enhancedWebHttp 的代码
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();
}
}
}
For any webprotocol exception the errorhandler should handle the exception and give only json response instead gives the page not found.
Here is the configuration for the service
<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>
Here is the Code for enhancedWebHttp
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
}
Here is the code for Licensing Behavior
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);
}
}
Here is the code for 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();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我创建了一个空的 ASP.NET 项目,将您所拥有的确切代码复制到其中(更改了一些命名空间,没有任何影响结果的内容),并且效果很好 - 在“json”端点中,WebProtocolException 以 JSON 形式返回格式,而在“pox”端点中,相同的异常以 XML 格式返回。您可以从 https://skydrive.live.com/?cid=99984bbbec66d789&sc=documents&uc=1&id=99984BBBEC66D789%21944#,并将其与您的实现进行比较,看看是否有什么不一样的。
I created an empty ASP.NET project, copied the exact code which you have into it (changed some namespaces, nothing which should affect the result), and it worked out just fine - in the "json" endpoint a WebProtocolException is returned in JSON format, while in the "pox" endpoint the same exception is returned in XML format. You can download the project (called SO_7498771.zip) from https://skydrive.live.com/?cid=99984bbbec66d789&sc=documents&uc=1&id=99984BBBEC66D789%21944#, and compare it with your implementation, to see if there is anything different.