Compartilhar via


Controle estendido através de relatórios e tratamento de erro

A amostra ErrorHandling demonstra como estender o controle sobre o tratamento e a geração de relatórios de erros em um serviço do Windows Communication Foundation (WCF) usando a interface IErrorHandler. A amostra é baseada na Introdução com algum código adicional adicionado ao serviço para lidar com erros. O cliente força várias condições de erro. O serviço intercepta os erros e registra-os em um arquivo.

Observação

O procedimento de instalação e as instruções de compilação dessa amostra estão no final deste tópico.

Os serviços podem interceptar erros, executar o processamento e afetar como os erros são relatados usando a interface IErrorHandler. A interface tem dois métodos que podem ser implementados: ProvideFault(Exception, MessageVersion, Message) e HandleError. O método ProvideFault(Exception, MessageVersion, Message) permite adicionar, modificar ou suprimir uma mensagem de falha gerada em resposta a uma exceção. O método HandleError permite que o processamento de erros ocorra no caso de um erro e controla se o tratamento de erro adicional pode ser executado.

Nesta amostra, o tipo CalculatorErrorHandler implementa a interface IErrorHandler. No

Método HandleError, o CalculatorErrorHandler grava um registro do erro em um arquivo de texto Error.txt em c:\logs. Observe que a amostra registra a falha e não a suprime, permitindo que ela seja relatada de volta ao cliente.

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

O ErrorBehaviorAttribute existe como um mecanismo para registrar um manipulador de erros com um serviço. Esse atributo usa um único parâmetro de tipo. Esse tipo deve implementar a interface IErrorHandler e deve ter um construtor público e vazio. Em seguida, o atributo cria uma instância desse tipo de manipulador de erros e o instala no serviço. Ele faz isso implementando a interface IServiceBehavior e, em seguida, usando o método ApplyDispatchBehavior para adicionar instâncias do manipulador de erros ao serviço.

// 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);
        }
    }
}

A amostra implementa um serviço de calculadora. O cliente faz com que ocorram deliberadamente dois erros no serviço fornecendo parâmetros com valores ilegais. O CalculatorErrorHandler usa a interface IErrorHandler para registrar os erros em um arquivo local e, em seguida, permite que eles sejam relatados de volta ao cliente. O cliente força uma divisão por zero e uma condição de argumento fora do intervalo.

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);
}

Quando você executa a amostra, as solicitações de operação e as respostas são exibidas na janela do console do cliente. Você vê a divisão por zero e as condições de argumento fora do intervalo sendo relatadas como falhas. Pressione ENTER na janela do cliente para desligar o cliente.

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.

O arquivo c:\logs\errors.txt contém as informações registradas sobre os erros pelo serviço. Observe que para o serviço gravar no diretório, você deve verificar se o processo no qual o serviço está em execução (normalmente ASP.NET ou Serviço de Rede) tem permissão para gravar no diretório.

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

Para configurar, compilar, e executar o exemplo

  1. Verifique se você executou o Procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Para compilar a solução, siga as instruções contidas em Compilar as amostras do Windows Communication Foundation.

  3. Verifique se você criou o diretório c:\logs para o arquivo error.txt. Ou modifique o nome do arquivo usado em CalculatorErrorHandler.HandleError.

  4. Para executar a amostra em uma configuração de computador único ou cruzado, siga as instruções em Como executar as amostras do Windows Communication Foundation.