使用企业库异常块的WCF异常屏蔽

Jon*_*ton 1 c# wcf enterprise-library exception-handling

我使用企业库来实现基于盖伊伯斯坦的博客文章例外屏蔽这里.我的实现基本上与他的相同,但是我有几个问题:

1:异常屏蔽的目的是不通过错误的确切细节,为什么映射指定从原始异常传递消息不变.什么是提供不太具体的消息的合理方式?

2:传回的faultexception包含来自原始异常的消息,因此无论我设法在故障合同中包装或返回什么,都可以获得有关故障的详细信息.有没有办法将信息删回回通用的"内部错误"消息.

请注意,如果我不使用[ExceptionShielding][FaultContract]属性,则服务将返回标准"服务器由于内部错误而无法处理请求"消息.

Ran*_*ica 5

如果您知道自己的应用程序异常不会泄露敏感信息,则可以处理这些特定异常并映射消息属性.对于其他例外,您可以跳过映射消息.此外,您可以在故障合同本身上指定exceptionMessage:

    <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      postHandlingAction="ThrowNewException" name="Exception">
      <exceptionHandlers>
        <add exceptionMessage="Oops! A System Error Occurred in the Service Layer." faultContractType="MyTypes.Exceptions.ServiceFault, MyTypes.Exceptions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
          type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF.FaultContractExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          name="Default Fault Contract Handler">
        </add>
Run Code Online (Sandbox Code Playgroud)

exceptionMessage将在FaultException的Message属性上填充.如果您没有映射细节,那么这可能就足够了.

如果您确实要在故障类中填充值,则可以分两步执行:

  1. 创建一个处理程序来处理您感兴趣的异常并清理消息.
  2. 创建一个处理程序来创建FaultContract

使用Guy Burstein的WCF异常处理和异常处理应用程序块集成示例这将设置ServiceFault的MessageText(其余部分基于该示例).

所以你的服务看起来像这样:

public int CreateOrder(string currency, double amount)
{
    try
    {
        throw new InvalidOperationException("Cannot call this operation!");
    }
    catch (Exception e)
    {
        // This sanitizes the message and throws a new Exception
        Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionPolicy.
            HandleException(e, "SanitizeAndThrow");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后在配置中,您将创建一个SanitizeAndThrow处理程序来清理消息:

  <add name="SanitizeAndThrow">
    <exceptionTypes>
      <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        postHandlingAction="ThrowNewException" name="Exception">
        <exceptionHandlers>
          <add exceptionMessage="This is a sanitized message." 
            replaceExceptionType="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
            name="Replace Handler" />
        </exceptionHandlers>
      </add>
    </exceptionTypes>
  </add>
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用异常屏蔽来创建FaultException:

  <add name="WCF Exception Shielding">
    <exceptionTypes>
      <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException" name="Exception">
        <exceptionHandlers>
          <add exceptionMessage="Oops!"
            type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF.FaultContractExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF"
            name="DefaultFaultContract Handler"
            faultContractType="Bursteg.Samples.WCFIntegration.ServiceContracts.ServiceFault, Bursteg.Samples.WCFIntegration.ServiceContracts">
            <mappings>
              <add name="Id" source="{Guid}"/>
              <add name="MessageText"  source="{Message}"/>
            </mappings>
          </add>
        </exceptionHandlers>
      </add>
Run Code Online (Sandbox Code Playgroud)

关于这个例子的一些注释:

  • 如果您没有清除异常,则可能会泄漏消息.这可以通过让"SanitizeAndThrow"处理程序抛出您自己的自定义异常并使屏蔽策略处理您的自定义类型并映射Message来减轻,但对于任何其他类型不执行任何映射.

  • 此代码不是生产就绪的,并不符合最佳实践.这只是一个例子和起点.例如,您通常不想捕获一般Exception,服务代码没有NotifyRethrow逻辑等.

  • 如果需要,您可以创建自定义错误契约处理程序来处理更复杂的方案.

  • 也许有一种更简单的方法来消除Detail故障异常(例如,异常屏蔽中的链接处理程序)?