WCF REST服务 - 通用异常处理
我有很多遗留代码,现在是WCF REST服务的后端 - 它以前是通常的WCF服务后端,如果这很重要的话。我想实现一种机制,可以捕捉任何方法中的任何异常并分析它。如果它是一个已知的错误,它将被处理并变成一个友善的外观错误。WCF REST服务 - 通用异常处理
我知道我可以抛出FaultException
或WebProtocolException
而不是'平常'异常,但是有很多地方在代码中抛出异常,并且寻找所有这些异常是一个非常痛苦的选择。
我想补充一点,创建一个新的行为凌驾于标准WebHttpBehavior.AddServerErrorHandlers
方法,并增加了我的错误处理程序(IErrorHandler
实现)到终点调度错误处理程序集合中的端点行为扩展。在错误处理程序内部,我分析异常并基于此异常创建(或不创建)期望的故障。
我希望这种机制能够为任何已知的异常返回自定义数据,但我错了。好的微软已经实现了一个美妙的不可避免的WebHttpBehavior2
,它无条件地将内部Microsoft.ServiceModel.Web.WebErrorHandler
添加到端点调度程序错误处理程序集合的末尾。这个处理程序会忽略所有以前执行的处理程序,只识别一小组例外,而大多数被解释为“内部服务器错误”,仅此而已。
问题是我是否在正确的路径上,并且有一种方法可以在WCF REST机制中禁用此处理程序,或者将其引入一个新的异常(例如,当任何异常被捕获,它首先由我处理处理程序,如果它们抛出/返回,例如FaultException,那么这个新异常将提供给Microsoft.ServiceModel.Web.WebErrorHandler
而不是原来的异常)。如果我所有使用IErrorHandler
和行为扩展的实验都毫无价值,那么有什么选择?再次,我真的不想修改异常抛出逻辑,我想要一个地方来捕捉异常并处理它们。
非常感谢!
当您将WCF SOAP服务更改为REST时,错误报告和处理更改的整个思路。
在SOAP中,错误是您合同的一部分。在REST中,它们只是成为您在HTTP响应代码和说明中输出的代码。
这里是一个catch片段:
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) {
}
}
MyErrorHandler是我的类实现IErrorHandler。
这看起来与我所做的非常相似。它是否适用于REST服务,还是仅适用于SOAP?如果它适用于REST服务,那么您是如何配置服务的?如果仅仅用于SOAP,那么谢谢,但就我现在看到的而言,REST是完全不同的故事。 – 2010-12-17 08:32:54
@Michael我为它做了REST服务。我是自我托管的,实际上创建了我自己的派生服务主机来设置行为。它都是基于代码的,没有XML。 – 2010-12-17 12:10:41
自我托管,我明白了...这就是我想的但被认为太复杂。谢谢! – 2010-12-17 15:28:29
这种捕获应该被添加到每种服务方法,对吧?或者有没有办法将它写在某个地方只处理一次以处理所有异常?我喜欢基于行为的方法,因为它为所有异常定义了一个通用处理程序,并且我不必担心为每个单一方法处理和处理异常。最好的情况是我为端点中的所有服务定义了一个处理器。我无法用你的方法达到这个目标,我可以吗? – 2010-12-17 08:30:07
设置'StatusDescription'不起作用!响应始终具有通用状态描述。无论如何解决它? – Hemant 2011-01-13 07:19:30
它有。您可以使用fiddler检查服务器发出的消息中的....,但是您可能会发现,各种浏览器或不同的实现可能会忽略该描述,只是使用代码映射到预定义的消息。我遇到了一个我正在编写的Android应用程序的问题,并最终设置了描述以及更改方法签名,以便我可以返回一个字符串。哎呀! **这就是为什么我永远不会使用WCF REST了。** – Aliostad 2011-01-13 09:19:02