Экранирование исключений WCF с использованием исключительного блока Enterprise Library - PullRequest
1 голос
/ 24 марта 2011

Я использую корпоративную библиотеку для реализации экранирования исключений на основе сообщения в блоге Гая Бурштейна здесь . Моя реализация в основном идентична его реализации, однако у меня есть пара проблем:

1: Экранирование исключительной ситуации не должно проходить через точные детали ошибки, так почему сопоставление указывает передачу сообщения из исходного исключения без изменений. Что было бы разумным способом предоставления менее конкретного сообщения?

2: Переданное ранее исключение faultexception содержит сообщение из исходного исключения, поэтому независимо от того, что мне удастся обернуть или вернуть в контракте о сбоях, подробности доступны по исключению faultexception. Есть ли способ удалить информацию обратно в общее сообщение "внутренняя ошибка".

Обратите внимание, что если я не использую атрибуты [ExceptionShielding] и [FaultContract], служба возвращает стандартное сообщение "Серверу не удалось обработать запрос из-за внутренней ошибки".

1 Ответ

5 голосов
/ 24 марта 2011

Если вы знаете, что у вас есть собственные исключения приложения, которые не раскрывают конфиденциальную информацию, вы можете обработать эти конкретные исключения и сопоставить свойство сообщения. Для других исключений вы можете пропустить отображение сообщения. Кроме того, вы можете указать сообщение исключения в самом договоре о сбое:

    <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>

exceptionMessage будет заполнено в свойстве Message FaultException. Если вы не отобразите детали, этого может быть достаточно для вас.

Если вы хотите заполнить значения в классе ошибок, вы можете сделать это в два этапа:

  1. Создайте обработчик (и) для обработки интересующего вас исключения и обработайте сообщение.
  2. Создание обработчика для создания FaultContract

Использование Обработка исключений WCF Гая Бурштейна с обработкой исключений Интеграция блока приложения Пример этого будет установка MessageText ServiceFault (остальное на этом примере).

Итак, ваш сервис будет выглядеть так:

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» генерирует собственное исключение, а политика экранирования обрабатывает ваши пользовательские типы и отображает сообщение, но для любого другого типа не выполняет сопоставление.

  • Этот код не готов к работе и не соответствует рекомендациям. Это всего лишь пример и отправная точка. например Вы обычно не хотите поймать общее Exception, сервисный код не имеет логики NotifyRethrow и т. д.

  • При необходимости вы можете создать пользовательский обработчик контракта ошибок, чтобы обрабатывать более сложные сценарии.

  • Возможно, существует более простой способ очистки Detail исключения ошибки (например, обработчики цепочек в экранировании исключения)?

...