所以我试图在我的 WCF 服务中使用企业库来为我做一些与异常相关的工作。
我的想法是为说“NullReferenceException”设置一个“自定义异常处理程序”,并在“自定义异常处理程序”中创建 FaultException 异常。
我的理解是,这个“新”异常将通过网络实现,我将在客户端捕获它。
一些代码可以更好地理解:
WCF 服务:
[ServiceContract(Name="MyService", ConfigurationName="MyNamespace.MyService")]
[ExceptionShielding("PolicyName")]
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyFaultContract))]
string Method(String Param);
}
public class MyService : IMyService
{
public string Method(String Param)
{
throw new NullReferenceException("code-created null message here");
}
}
自定义异常处理程序:(企业库)
public class MyExceptionHandler : IExceptionHandler
{
public MyExceptionHandler(NameValueCollection collection) { }
public MyExceptionHandler() { }
public System.Exception HandleException(System.Exception exception,
Guid handlingInstanceId)
{
MyFaultContract details = new MyFaultContract();
if (exception is NullReferenceException)
{
details.ErrorCode = MyFaultCode.NullReferenceException;
details.OriginalMessage = exception.Message;
details.MyMessage = "Null Reference exception here!";
}
return new FaultException<MyFaultContract>(details);
}
}
将 NullReferenceException 映射到“自定义异常处理程序”的应用程序配置文件:
<exceptionPolicies>
<add name="PolicyName">
<exceptionTypes>
<add name="NullReferenceException" type="System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="ThrowNewException">
<exceptionHandlers>
<add type="MyExceptionHandler, MyApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="MyExceptionHandler" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
最后是期望捕获此 FaultException 的客户端代码:
MyService.MyServiceClient client = new MyService.MyServiceClient();
client.Open();
try
{
string result = client.Method(string parameter);
}
catch (System.ServiceModel.FaultException<MyService.MyFaultContract> ex)
{
// where I think exception should end up
}
catch (System.ServiceModel.FaultException ex)
{
// general FaultException
}
但相反,我得到一个 ProtocolException,说明需要回复操作:
收到操作“方法”的回复消息,操作为“”。但是,您的客户端代码需要操作“http://tempuri.org/MyService/MethodResponse”。
我究竟做错了什么?是否可以在“自定义异常处理程序”中返回(不显式抛出)带有自定义 FaultContract 的 FaultException?
任何建议表示赞赏。
更新: 如您所见,“自定义异常处理程序”中的后处理操作设置为“ThrowNewException”。如果我将其更改为“NotifyRethrow”,我将不再使用“ProtocolException”!相反,客户端会捕获常规的“FaultException”(不是自定义类型的)。
现在的问题是为什么原始的自定义类型的 FaultException 不能跨越网络。
更新 2 我忘记提及的一件事是我的 WCF 服务在 ServiceHost 中运行,而不是在 IIS 下运行。所以基本上我有一个 Windows 服务,它创建一个 ServiceHost 并通过这个 ServiceHost 公开 Service1 接口。
我认为这可能与此问题有关的原因是 Enterprise Library 声称它处理整个应用程序中的异常,而不仅仅是在服务边界内。也许这会导致异常被抛出为时已晚?还是不在正确的水平?
更新 3
感谢您的帖子!你是对的,我搞乱自定义处理程序的唯一原因是因为我想设置 MyFaultCode 值。我尝试了您的建议 - 配置了 2 个处理程序。
首先是一个自定义处理程序并捕获 NullReference 异常。它会引发一个新异常 - MyApplicationException,带有 MyFaultContract 字段。
然后我配置了第二个处理程序 - 内置的“Fault Contract Exception Handler”,它捕获 MyApplicationException,创建新的 FaultException 并自动将 MyFaultcontract 从 MyApplicationException 映射到新创建的 FaultException。
WCF 客户端仍然捕获通用的 FaultException,而不是自定义合同。