我想为我的WCF应用程序实现一个适当的异常处理。在谷歌搜索了一下之后,我发现了两个解决方案。
- 为客户端提供
FaultExceptions
- 使用
IErrorHandler
处理一般异常。
我的想法:
抛出带有自己详细类型的faultexception
throw new FaultException<StackOverflowFault>(
new StackOverflowFault(StackOverflowFaultCode.Rules,
"This question is not considered as constructive."));
用IErrorHandler
捕获未处理的异常并记录它们
public bool HandleError(Exception ex) {
try {
SomeLogger.Error(ex.Message, ex.Source);
return true;
} catch (Exception) {
// Well, there was an exception handling the
// exception :(
// -> Drop the exception and throw a new one
throw new Exception("Unknown exception occured.");
}
}
…并根据异常类型
提供故障(不是一切都是为了客户的眼睛!)
public void ProvideFault(Exception error, MessageVersion version, ref Message fault){
if(error is FaultException) {
fault = Message.CreateMessage(version, ((FaultException<StackOverflowFault>)error).Reason)
} else if(error is SqlException) {
// What would Jon Skeet do?
}
}
我的问题
这被认为是好的做法吗?并且:如果我已经在适合客户端的应用程序中抛出FaultException -让它们由IErrorHandler
(它自动)处理有意义吗?
最佳实践是实现IErrorHandler。这是因为:
- 你的代码不是唯一潜在的异常来源。你调用的方法(或者一个bug)可能会导致。net异常。如果您没有在某个地方处理该异常,并且没有使用IncludeExceptionDetailInFaults(在生产环境中不应该这样做),这将看起来像服务崩溃。
-
关注点分离:服务代码调用的任何业务层都不应该引用WCF (
System.ServiceModel
),因此应该抛出标准的。net异常。保持业务层不知道它是如何托管的,使它更易于移植和更可测试。 - [
FaultContract
]类型需要在[OperationContract
]上指定。在较大的应用程序中,您希望集中生成Fault,换句话说,知道特定的IErrorHandler返回特定的一组Fault,以便您可以验证契约的Fault类型是否正确。抛出合约方法不明确支持的Fault类型是一个严重的运行时错误。
你可以在你所有的服务方法中复制粘贴一个try/catch块来抛出一个FaultException,但是这是一个可怕的代码气味,并且是IErrorHandler作为一种行为给你的确切功能。所以用IErrorHandler来代替。
将两种模型结合起来是可能的。例如,让IErrorHandler根据需要处理FaultExceptions,但这不是一种常见的做法。