Rozszerzanie kontroli obsługi i raportowania błędów

W przykładzie ErrorHandling pokazano, jak rozszerzyć kontrolę nad obsługą błędów i raportowaniem błędów w usłudze Windows Communication Foundation (WCF) przy użyciu interfejsu IErrorHandler . Przykład jest oparty na kodzie Wprowadzającym dodanym do usługi w celu obsługi błędów. Klient wymusza kilka warunków błędu. Usługa przechwytuje błędy i rejestruje je w pliku.

Uwaga

Procedura instalacji i instrukcje kompilacji dla tego przykładu znajdują się na końcu tego tematu.

Usługi mogą przechwytywać błędy, przetwarzać i wpływać na sposób zgłaszania błędów przy użyciu interfejsu IErrorHandler . Interfejs ma dwie metody, które można zaimplementować: ProvideFault(Exception, MessageVersion, Message) i HandleError. Metoda ProvideFault(Exception, MessageVersion, Message) umożliwia dodawanie, modyfikowanie lub pomijanie komunikatu o błędzie wygenerowanego w odpowiedzi na wyjątek. Metoda HandleError umożliwia przetwarzanie błędów w przypadku błędu i określa, czy można uruchomić dodatkową obsługę błędów.

W tym przykładzie CalculatorErrorHandler typ implementuje IErrorHandler interfejs. W

HandleError metoda zapisuje CalculatorErrorHandler dziennik błędu w pliku tekstowym Error.txt w c:\logs. Należy pamiętać, że przykład rejestruje błąd i nie pomija go, co pozwala na zgłaszanie go z powrotem do klienta.

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

Istnieje ErrorBehaviorAttribute jako mechanizm rejestrowania programu obsługi błędów w usłudze. Ten atrybut przyjmuje pojedynczy parametr typu. Ten typ powinien implementować IErrorHandler interfejs i powinien mieć publiczny, pusty konstruktor. Następnie atrybut tworzy wystąpienie tego typu procedury obsługi błędów i instaluje je w usłudze. Robi to przez zaimplementowanie interfejsu IServiceBehavior , a następnie użycie ApplyDispatchBehavior metody w celu dodania wystąpień programu obsługi błędów do usługi.

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

Przykład implementuje usługę kalkulatora. Klient celowo powoduje wystąpienie dwóch błędów w usłudze przez podanie parametrów z niedozwolonymi wartościami. Narzędzie CalculatorErrorHandler używa interfejsu IErrorHandler do rejestrowania błędów w pliku lokalnym, a następnie umożliwia zgłaszanie ich z powrotem do klienta. Klient wymusza podzielenie przez zero i warunek argumentu poza zakresem.

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

Po uruchomieniu przykładu żądania operacji i odpowiedzi są wyświetlane w oknie konsoli klienta. Podział według zera i warunki argumentu poza zakresem są zgłaszane jako błędy. Naciśnij klawisz ENTER w oknie klienta, aby zamknąć klienta.

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.

Plik c:\logs\errors.txt zawiera informacje rejestrowane o błędach przez usługę. Należy pamiętać, że aby usługa zapisywała dane w katalogu, upewnij się, że proces, w którym działa usługa (zazwyczaj ASP.NET lub usługa sieciowa), ma uprawnienia do zapisu w katalogu.

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

Aby skonfigurować, skompilować i uruchomić przykład

  1. Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.

  2. Aby skompilować rozwiązanie, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).

  3. Upewnij się, że utworzono katalog c:\logs dla pliku error.txt. Lub zmodyfikuj nazwę pliku używaną w pliku CalculatorErrorHandler.HandleError.

  4. Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.