.net WCF REST服务-通用异常处理

.net WCF REST服务-通用异常处理,.net,wcf,rest,.net,Wcf,Rest,我有很多遗留代码,现在是WCF REST服务的后端——如果有必要的话,它以前是一个普通的WCF服务后端。我想实现一种机制,可以捕获任何方法中的任何异常并对其进行分析。如果它被证明是一个已知错误,它将被处理并转化为一个外观友好的错误 我知道我可以抛出FaultException或WebProtocolException而不是“通常”的异常,但是在很多地方,异常都会在代码中抛出,寻找所有异常是一个相当痛苦的选择 我试图添加一个端点行为扩展,该扩展创建一个新的行为,该行为覆盖标准的WebHttpBeh

我有很多遗留代码,现在是WCF REST服务的后端——如果有必要的话,它以前是一个普通的WCF服务后端。我想实现一种机制,可以捕获任何方法中的任何异常并对其进行分析。如果它被证明是一个已知错误,它将被处理并转化为一个外观友好的错误

我知道我可以抛出
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。我明白了。这是我一直在想的,但被认为太复杂了。谢谢!