Повышение управляемости обработки ошибок и формирования сообщений об ошибках

В примере 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. Убедитесь, что вы выполнили процедуру однократной установки для примеров Windows Communication Foundation.

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

  3. Проверьте, что создан каталог c:\logs для файла error.txt. Либо измените имя файла, используемое в CalculatorErrorHandler.HandleError.

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