扩展对错误处理和报告的控制

ErrorHandling 示例演示如何使用IErrorHandler接口扩展对 Windows Communication Foundation (WCF) 服务中的错误处理和错误报告的控制。 此示例基于入门,并在服务中添加了一些代码以处理错误。 客户端强制实施若干个错误条件。 服务截获错误并将其记录在文件中。

注释

本示例的设置过程和生成说明位于本主题末尾。

服务可以截获错误、执行处理以及影响如何使用 IErrorHandler 接口报告错误。 该接口有两个可以实现的方法: ProvideFault(Exception, MessageVersion, Message)HandleError。 使用 ProvideFault(Exception, MessageVersion, Message) 此方法,可以添加、修改或取消响应异常时生成的错误消息。 此方法 HandleError 允许在发生错误时进行错误处理,并控制是否可以运行其他错误处理。

在此示例中,该 CalculatorErrorHandler 类型实现 IErrorHandler 接口。 在

HandleError 方法会将 CalculatorErrorHandler 错误日志记录到 c:\logs 文件夹中的 Error.txt 文本文件。 请注意,示例会记录错误,但不会抑制错误,这样就可以将其反馈给客户端。

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

运行示例时,操作请求和响应将显示在客户端控制台窗口中。 你将看到除以零的除法运算和自变量超出范围的情况被报告为错误。 在客户端窗口中按 Enter 关闭客户端。

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 示例 执行One-Time 安装过程。

  2. 要生成解决方案,请按照生成 Windows Communication Foundation 示例中的说明进行操作。

  3. 确保已创建 c:\logs directory for the error.txt 文件。 或者修改在CalculatorErrorHandler.HandleError中使用的文件名。

  4. 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。