Расширение контроля над обработкой ошибок и отчетами

В примере ErrorHandling показано, как расширить контроль над обработкой ошибок и отчетами об ошибках в службе Windows Communication Foundation (WCF) с помощью IErrorHandler интерфейса. Пример основан на руководстве "Начало работы" с добавлением дополнительного кода в службу для обработки ошибок. Клиент вызывает несколько условий ошибки. Служба перехватывает ошибки и регистрирует их в файле.

Замечание

Процедура установки и инструкции по сборке для этого примера находятся в конце этого раздела.

Службы могут перехватывать ошибки, выполнять обработку и влиять на то, как сообщается об ошибках с помощью IErrorHandler интерфейса. Интерфейс имеет два метода, которые можно реализовать: ProvideFault(Exception, MessageVersion, Message) и HandleError. Метод ProvideFault(Exception, MessageVersion, Message) позволяет добавлять, изменять или подавлять сообщение об ошибке, созданное в ответ на исключение. Метод HandleError позволяет выполнять обработку ошибок в случае ошибки и определяет, может ли выполняться дополнительная обработка ошибок.

В этом примере тип CalculatorErrorHandler реализует интерфейс IErrorHandler. В

Метод HandleError записывает журнал ошибки CalculatorErrorHandler в текстовый файл Error.txt, расположенный в c:\logs. Обратите внимание, что пример фиксирует ошибку и не подавляет её, что позволяет сообщить о ней обратно клиенту.

public class CalculatorErrorHandler : IErrorHandler
{
    // Provide a fault. The Message fault parameter can be replaced, or set to
    // null to suppress reporting a fault.

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
    }

    // HandleError. Log an error, then allow the error to be handled as usual.
    // Return true if the error is considered as already handled

    public bool HandleError(Exception error)
    {
        using (TextWriter tw = File.AppendText(@"c:\logs\error.txt"))
        {
            if (error != null)
            {
                tw.WriteLine("Exception: " + error.GetType().Name + " - " + error.Message);
            }
            tw.Close();
        }
        return true;
    }
}

Механизм ErrorBehaviorAttribute существует для регистрации обработчика ошибок с сервисом. Этот атрибут принимает один параметр типа. Этот тип должен реализовать IErrorHandler интерфейс и должен иметь открытый, пустой конструктор. Затем атрибут создает экземпляр этого типа обработчика ошибок и устанавливает его в службу. Это делается путем реализации IServiceBehavior интерфейса, а затем с помощью ApplyDispatchBehavior метода для добавления экземпляров обработчика ошибок в службу.

// This attribute can be used to install a custom error handler for a service.
public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
{
    Type errorHandlerType;

    public ErrorBehaviorAttribute(Type errorHandlerType)
    {
        this.errorHandlerType = errorHandlerType;
    }

    void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
    }

    void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
    {
    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
        IErrorHandler errorHandler;

        try
        {
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
        }
        catch (MissingMethodException e)
        {
            throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must have a public empty constructor.", e);
        }
        catch (InvalidCastException e)
        {
            throw new ArgumentException("The errorHandlerType specified in the ErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
        }

        foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
            channelDispatcher.ErrorHandlers.Add(errorHandler);
        }
    }
}

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

try
{
    Console.WriteLine("Forcing an error in Divide");
    // Call the Divide service operation - trigger a divide by 0 error.
    value1 = 22;
    value2 = 0;
    result = proxy.Divide(value1, value2);
    Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
}
catch (FaultException e)
{
    Console.WriteLine("FaultException: " + e.GetType().Name + " - " + e.Message);
}
catch (Exception e)
{
    Console.WriteLine("Exception: " + e.GetType().Name + " - " + e.Message);
}

При запуске примера запросы и ответы операции отображаются в окне консоли клиента. Вы видите деление на ноль и условия выхода аргумента за пределы диапазона, сообщаемые как сбои. Нажмите клавишу ВВОД в окне клиента, чтобы завершить работу клиента.

Add(15,3) = 18
Subtract(145,76) = 69
Multiply(9,81) = 729
Forcing an error in Divide
FaultException: FaultException - Invalid Argument: The second argument must not be zero.
Forcing an error in Factorial
FaultException: FaultException - Invalid Argument: The argument must be greater than zero.

Press <ENTER> to terminate client.

Файл c:\logs\errors.txt содержит сведения, записанные в журнал об ошибках службы. Обратите внимание, что для записи службы в каталог необходимо убедиться, что процесс выполнения службы (обычно ASP.NET или сетевой службы) имеет разрешение на запись в каталог.

Fault: Reason = Invalid Argument: The second argument must not be zero.
Fault: Reason = Invalid Argument: The argument must be greater than zero.

Настройка, сборка и запуск примера

  1. Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.

  2. Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.

  3. Убедитесь, что вы создали файл c:\logs directory for the error.txt. Или измените имя файла, используемое в CalculatorErrorHandler.HandleError.

  4. Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.