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

时间:2011-03-24 12:34:46

标签: c# wcf exception-handling enterprise-library

我正在使用企业库来实现基于Guy Burstein的博客文章here的异常屏蔽。我的实现与他的实现基本相同,但是我有几个问题:

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

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

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

1 个答案:

答案 0 :(得分: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>
将在FaultException的Message属性上填充

exceptionMessage。如果您没有映射细节,那么这对您来说就足够了。

如果您确实希望在故障类中填充值,那么您可以分两步完成:

  1. 创建一个处理程序来处理您感兴趣的异常并清理消息。
  2. 创建处理程序以创建FaultContract
  3. 使用Guy Burstein's WCF Exception Handling with Exception Handling Application Block Integration示例,这将设置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;
    }
    

    然后在配置中,您将创建一个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>
    

    然后,您可以使用异常屏蔽来创建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>
    

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

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

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

    • 如果需要,您可以创建自定义故障合同处理程序来处理更复杂的方案。

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