Estensione del controllo sulla gestione e sulla segnalazione degli errori
L'esempio ErrorHandling illustra come estendere il controllo sulla gestione degli errori e la segnalazione degli errori in un servizio Windows Communication Foundation (WCF) tramite l'interfaccia IErrorHandler. L'esempio è basato sull’Introduzione, con ulteriore codice aggiunto al servizio per gestire gli errori. Il client forza diverse condizioni di errore. Il servizio intercetta gli errori e li registra in un file.
Nota
La procedura di installazione e le istruzioni di compilazione per questo esempio si trovano alla fine di questo argomento.
I servizi possono intercettare gli errori, eseguire l'elaborazione e influire sulla segnalazione degli errori utilizzando l'interfaccia IErrorHandler. L'interfaccia dispone di due metodi che possono essere implementati: ProvideFault(Exception, MessageVersion, Message) e HandleError. Il metodo ProvideFault(Exception, MessageVersion, Message) consente di aggiungere, modificare o sopprimere un messaggio di errore generato in risposta a un'eccezione. Se si verifica un errore, il metodo HandleError consente l'elaborazione dell'errore e controlla se è possibile eseguire una gestione aggiuntiva degli errori.
In questo esempio, il tipo CalculatorErrorHandler
implementa l'interfaccia IErrorHandler. Nel campo
metodo HandleError, CalculatorErrorHandler
scrive un registro dell'errore nel file di testo Error.txt in c:\logs. Si noti che nell'esempio l'errore viene registrato e non soppresso, in modo da poter essere segnalato al client.
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
funge da meccanismo per registrare un gestore di errori con un servizio. Questo attributo accetta un solo parametro di tipo. Tale tipo deve implementare l'interfaccia IErrorHandler e deve disporre di un costruttore pubblico vuoto. L'attributo crea quindi un'istanza di quel tipo di gestore errori e la installa nel servizio. Questa operazione viene eseguita implementando l'interfaccia IServiceBehavior e quindi utilizzando il metodo ApplyDispatchBehavior per aggiungere istanze del gestore errori al servizio.
// 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);
}
}
}
Nell'esempio viene implementato un servizio calcolatrice. Il client causa deliberatamente due errori nel servizio fornendo parametri con valori non validi. CalculatorErrorHandler
utilizza l'interfaccia IErrorHandler per registrare gli errori in un file locale e quindi consente che siano segnalati al client. Il client forza una divisione per zero e una condizione di argomento esterno all'intervallo.
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 si esegue l'esempio, le richieste e le risposte dell'operazione vengono visualizzate nella finestra della console client. Viene visualizzata la divisione per zero e le condizioni di argomento esterno all'intervallo segnalate come errori. Premere INVIO nella finestra del client per arrestare il client.
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.
Il file c:\logs\errors.txt contiene le informazioni registrate sugli errori dal servizio. Si noti che affinché il servizio scriva nella directory è necessario assicurarsi che il processo in cui è in esecuzione il servizio (in genere ASP.NET o servizio di rete) disponga dell’autorizzazione per scrivere nella directory.
Fault: Reason = Invalid Argument: The second argument must not be zero.
Fault: Reason = Invalid Argument: The argument must be greater than zero.
Per impostare, compilare ed eseguire l'esempio
Assicurarsi di aver eseguito la Procedura di installazione singola per gli esempi di Windows Communication Foundation.
Per compilare la soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.
Assicurarsi di aver creato la directory c:\logs per il file error.txt. In alternativa, modificare il nome file utilizzato in
CalculatorErrorHandler.HandleError
.Per eseguire l'esempio in un solo computer o tra computer diversi, seguire le istruzioni in Esecuzione degli esempi di Windows Communication Foundation.