.net WCF REST服务-通用异常处理
我有很多遗留代码,现在是WCF REST服务的后端——如果有必要的话,它以前是一个普通的WCF服务后端。我想实现一种机制,可以捕获任何方法中的任何异常并对其进行分析。如果它被证明是一个已知错误,它将被处理并转化为一个外观友好的错误 我知道我可以抛出.net WCF REST服务-通用异常处理,.net,wcf,rest,.net,Wcf,Rest,我有很多遗留代码,现在是WCF REST服务的后端——如果有必要的话,它以前是一个普通的WCF服务后端。我想实现一种机制,可以捕获任何方法中的任何异常并对其进行分析。如果它被证明是一个已知错误,它将被处理并转化为一个外观友好的错误 我知道我可以抛出FaultException或WebProtocolException而不是“通常”的异常,但是在很多地方,异常都会在代码中抛出,寻找所有异常是一个相当痛苦的选择 我试图添加一个端点行为扩展,该扩展创建一个新的行为,该行为覆盖标准的WebHttpBeh
FaultException
或WebProtocolException
而不是“通常”的异常,但是在很多地方,异常都会在代码中抛出,寻找所有异常是一个相当痛苦的选择
我试图添加一个端点行为扩展,该扩展创建一个新的行为,该行为覆盖标准的WebHttpBehavior.AddServerErrorHandlers
方法,并将我的错误处理程序(IErrorHandler
实现)添加到端点调度程序错误处理程序集合中。在错误处理程序中,我分析异常并基于该异常创建(或不创建)所需的故障
我希望这个机制能够为任何已知的异常返回自定义数据,但我错了。好的老微软已经实现了一个奇妙的WebHttpBehavior2
,它无条件地将一个内部Microsoft.ServiceModel.Web.WebErrorHandler
添加到endpoint dispatcher错误处理程序集合的末尾。此处理程序忽略所有以前执行的处理程序,只识别一小部分异常,而大多数异常被解释为“内部服务器错误”,仅此而已
问题是我是否走在正确的道路上,是否有办法在WCF REST机制中禁用此处理程序,或者使用新的异常引入它(例如,当捕获任何异常时,它首先由我的处理程序处理,如果它们抛出/返回,例如FaultException,则此新异常将提供给Microsoft.ServiceModel.Web.WebErrorHandler
,而不是原始异常)。如果我对IErrorHandler
和行为扩展的所有实验都一文不值,那么还有什么替代方案呢?再说一遍,我真的不想修改异常引发逻辑,我想要一个地方来捕获异常并处理它们
非常感谢!当您将WCF SOAP服务更改为REST时,错误报告和处理的整个思维方式都会发生变化 在SOAP中,错误是契约的一部分,而在REST中,它们只是成为您在HTTP响应代码和描述中输出的代码 下面是一个捕获片段:
catch (Exception e)
{
Trace.WriteLine(e.ToString());
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = System.Net.HttpStatusCode.UnsupportedMediaType; // or anything you want
response.StatusDescription = e.Message;
return null; // I was returning a class
}
因此,我建议您创建一个帮助代码,为您创建相关的错误代码,并将其放入响应中。这就是我过去所做的
public class MyServerBehavior : IServiceBehavior {
public void AddBindingParameters(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters) {
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase) {
foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) {
chDisp.IncludeExceptionDetailInFaults = true;
if (chDisp.ErrorHandlers.Count > 0) {
// Remove the System.ServiceModel.Web errorHandler
chDisp.ErrorHandlers.Remove(chDisp.ErrorHandlers[0]);
}
// Add new custom error handler
chDisp.ErrorHandlers.Add(new MyErrorHandler());
}
}
public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase) {
}
}
公共类MyServerBehavior:IServiceBehavior{
public void AddBindingParameters(ServiceDescription ServiceDescription,
ServiceHostBase ServiceHostBase,
集合终结点,
BindingParameterCollection(绑定参数){
}
public void ApplyDispatchBehavior(ServiceDescription ServiceDescription,
服务主机库(服务主机库){
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher chDisp){
chDisp.IncludeExceptionDetailInFaults=true;
如果(chDisp.ErrorHandlers.Count>0){
//删除System.ServiceModel.Web errorHandler
chDisp.ErrorHandlers.Remove(chDisp.ErrorHandlers[0]);
}
//添加新的自定义错误处理程序
添加(新的MyErrorHandler());
}
}
公共无效验证(ServiceDescription ServiceDescription,
服务主机库(服务主机库){
}
}
MyErrorHandler是我实现IErrorHandler的类。这样的捕获应该添加到每个服务方法中,对吗?或者有没有一种方法可以在某个地方只编写一次来处理所有异常?我喜欢基于行为的方法,因为它为所有异常定义了一个公共处理程序,我不必担心处理和processing每个方法都有例外。最好的是,我为端点中的所有服务定义了一个处理器。我无法使用您的方法实现这一点,可以吗?设置
StatusDescription
没有效果!响应始终具有通用状态描述。是否有办法修复它?它有。您可以在传出的mes中检查这一点sage来自使用fiddler的服务器,…。但您往往会发现,不同的浏览器或不同的实现可能会忽略描述,而只是使用代码映射到预定义的消息。我在制作的Android应用程序中遇到了这一问题,我最终设置了描述并更改了方法签名,以便能够这是为什么我再也不会使用WCF REST了。@ Aliostad,你有没有考虑过为StutsMe留言返回自定义响应头值?我不知道WCF的错误是客户端不尊重状态描述所设置的值吗?也许我漏掉了什么东西?不是真的。这将是反HTTP。ST。atus代码是状态代码,尽管您可以有自定义代码,例如909“我的自定义状态”。这看起来与我所做的非常相似。它是为REST服务工作的,还是仅为SOAP工作?如果它为REST服务工作,您是如何配置服务的?如果只是为SOAP工作,那么谢谢您,但就我现在看来,REST是一个完全不同的故事。@Michael,我是为REST服务工作的。我是自托管的,实际上创建了自己的派生服务设置行为的ice主机。它都是基于代码的,没有XML。我明白了。这是我一直在想的,但被认为太复杂了。谢谢!