Обработка исключений в корпоративной библиотеке для контрактов на отказ WCF - СТОРОНА КЛИЕНТА - PullRequest
0 голосов
/ 13 мая 2010

У меня есть служба Windows, которая взаимодействует со службами WCF. Все службы WCF защищены от сбоев и генерируют пользовательские UserFaultContracts и ServiceFaultContracts. Там нет проблем.

В службе Windows я использую EntLib для обработки исключений и ведения журнала.

Я не хочу пробовать ловить при неисправностях

try
{
}
catch (FaultException<UserFaultContract>)
{
}

Я хочу использовать EntLib

try
{
}
catch (Exception ex)
{
var rethrow = ExceptionPolicy.HandleException(ex, "Transaction Policy");
if (rethrow) throw;
}

Это также работает, однако, в моей Политике Tranasaction я хочу Записать детали UserFaultContract. Это где я склеен. И я ненавижу, когда меня расклеивают. Ошибка фиксируется и регистрируется ... но я не могу получить подробную информацию о ней.

Моя политика исключений

  <add name="Transaction Policy">
    <exceptionTypes>
      <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        postHandlingAction="None" name="Exception">
        <exceptionHandlers>
          <add logCategory="General" eventId="200" severity="Error" title="Transaction Error"
            formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            priority="2" useDefaultLogger="true" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            name="Logging Handler" />
        </exceptionHandlers>
      </add>
      <add type="System.ServiceModel.FaultException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        postHandlingAction="None" name="FaultException">
        <exceptionHandlers>
          <add logCategory="General" eventId="200" severity="Error" title="Service Fault"
            formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            priority="2" useDefaultLogger="true" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            name="Logging Handler" />
        </exceptionHandlers>
      </add>
    </exceptionTypes>
  </add>

Зарегистрировано исключение:

Метка времени: 13.05.2010 14:53:40 Сообщение: HandlingInstanceID: e9038634-e16e-4d87-ab1e-92379431838b

Исключение типа 'System.ServiceModel.FaultException`1 [[LCI.DispatchMaster.FaultContracts.ServiceFaultContract, LCI.DispatchMaster.FaultContracts, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]]' возникло и было пойманы.

05/13/2010 10:53:40 Тип: System.ServiceModel.FaultException`1 [[LCI.DispatchMaster.FaultContracts.ServiceFaultContract, LCI.DispatchMaster.FaultContracts, Версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = null]], System.ServiceModel, версия = 3.0.0.0 , Культура = нейтральный, PublicKeyToken = b77a5c561934e089 Сообщение. Произошла внутренняя ошибка службы DispatchMaster. Источник: mscorlib Справочная ссылка: Деталь: LCI.DispatchMaster.FaultContracts.ServiceFaultContract Действие: http://LCI.DispatchMaster.LogicalChoices.com/ITruckMasterService/MergeScenarioServiceFaultContractFault Код: System.ServiceModel.FaultCode Причина: произошла внутренняя ошибка в службе DispatchMaster. Данные: System.Collections.ListDictionaryInternal TargetSite: Void HandleReturnMessage (System.Runtime.Remoting.Messaging.IMessage, System.Runtime.Remoting.Messaging.IMessage) Трассировка стека:

В контакте неисправности есть ID и сообщение. Как вы видите, мне бы хотелось, чтобы идентификатор и сообщение регистрировались EntLib.

Я предполагаю, что мне придется написать собственный обработчик для извлечения подробностей ошибки - но подумал, что я спрошу, если я что-то упустил в EntLib, что может помочь мне избежать этой задачи.

Спасибо всем, кто готов помочь.

Ответы [ 2 ]

0 голосов
/ 04 ноября 2014

Если вы уверены, что в службе WCF все настроено правильно, вы сможете получить сообщение, заполненное вами на стороне службы.

Следующий код должен отображать полную информацию об исключениях на стороне клиента.

private void CalculateDivision(decimal numerator, decimal denominator)
{
    try
    {
        // Create an instance of service client.
        ICalculatorService svc = new CalculatorServiceClient();
        // Call service method.
        Console.WriteLine("Result is: {0}", svc.Divide(numerator, denominator));
    }
    catch (Exception ex)
    {
        // Show details of the exception returned to the calling code.  
        ShowExceptionDetails(ex);
        // Show details of the fault contract returned from the WCF service.  
        ShowFaultContract(ex);
    }
}


public void ShowExceptionDetails(Exception ex)
{
    Console.WriteLine("Exception type {0} was thrown.", ex.GetType().ToString());
    Console.WriteLine("Message: '{0}'", ex.Message);
    Console.WriteLine("Source: '{0}'", ex.Source);
    if (null == ex.InnerException)
    {
        Console.WriteLine("No Inner Exception");
    }
    else
    {
        Console.WriteLine();
        Console.WriteLine("Inner Exception: {0}", ex.InnerException.ToString());
    }
    Console.WriteLine();
}

private static void ShowFaultContract(Exception ex)
{
    var faultContract = ex as FaultException<CalculatorFault>;
    if (faultContract != null)
    {
        CalculatorFault calculatorFault = faultContract.Detail;
        Console.WriteLine("Fault contract detail: ");
        Console.WriteLine("Fault ID: {0}", calculatorFault.FaultID);
        Console.WriteLine("Message: {0}", calculatorFault.FaultMessage);
    }
}

Если это все еще не работает, значит, что-то не так на стороне службы наверняка. Давайте посмотрим, как должен выглядеть сервисный код для определенного клиента, определенного выше.

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    [FaultContract(typeof(CalculatorFault))]
    decimal Divide(decimal num1, decimal num2);
}

[DataContract]
public class CalculatorFault
{
    [DataMember]
    public Guid FaultID { get; set; }

    [DataMember]
    public string FaultMessage { get; set; }
}

[ExceptionShielding("CalculatorServicePolicy")]
public class CalculatorService : ICalculatorService
{
    public decimal Divide(decimal num1, decimal num2)
    {
      Calculator calc = new Calculator();
      return calc.Divide(num1, num2);
    }
}

//Call the following function in Application_Start function of your Global.asax file
private void ConfigureExceptionHandlingBlock()
{
    var policies = new List<ExceptionPolicyDefinition>();

    var mappings = new NameValueCollection();
    mappings.Add("FaultID", "{Guid}");
    mappings.Add("FaultMessage", "{Message}");

    var calculatorServicePolicy = new List<ExceptionPolicyEntry>
        {
            new ExceptionPolicyEntry(typeof(Exception),
                PostHandlingAction.ThrowNewException,
                new IExceptionHandler[]
                {
                    new FaultContractExceptionHandler(typeof(CalculatorFault), "Some internal service Error. Check service logs.", mappings)
                })
        };
    policies.Add(new ExceptionPolicyDefinition("CalculatorServicePolicy", calculatorServicePolicy));
    ExceptionManager exManager = new ExceptionManager(policies);
    ExceptionPolicy.SetExceptionManager(exManager);
}
0 голосов
/ 13 мая 2010

На самом деле я сейчас очень похож на исследование того, как правильно бороться с ошибками WCF и EAB. Я думаю эта статья может оказаться чрезвычайно полезной для вас. Я не пробовал, но это не выглядит слишком скучно.

...