错误协定

错误示例演示如何将错误信息从服务传达给客户端。 此示例基于 “入门”,向服务添加了一些附加代码,用于将内部异常转换为错误。 客户端尝试通过零进行除法,以强制服务进入错误状态。

注释

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

已修改的计算器协议中包含了一个 FaultContractAttribute,如以下示例代码所示。

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    int Add(int n1, int n2);
    [OperationContract]
    int Subtract(int n1, int n2);
    [OperationContract]
    int Multiply(int n1, int n2);
    [OperationContract]
    [FaultContract(typeof(MathFault))]
    int Divide(int n1, int n2);
}

FaultContractAttribute 属性指示 Divide 操作可能会返回类型为 MathFault 的错误。 错误可以是可序列化的任何类型的。 在这种情况下,MathFault 是一个数据合同,如下:

[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public class MathFault
{
    private string operation;
    private string problemType;

    [DataMember]
    public string Operation
    {
        get { return operation; }
        set { operation = value; }
    }

    [DataMember]
    public string ProblemType
    {
        get { return problemType; }
        set { problemType = value; }
    }
}

当发生除以零异常时,该方法 Divide 将引发 FaultException<TDetail> 异常,如以下示例代码所示。 此异常导致向客户端发送一个错误。

public int Divide(int n1, int n2)
{
    try
    {
        return n1 / n2;
    }
    catch (DivideByZeroException)
    {
        MathFault mf = new MathFault();
        mf.operation = "division";
        mf.problemType = "divide by zero";
        throw new FaultException<MathFault>(mf);
    }
}

通过请求除数为零,客户端代码强制产生错误。 运行示例时,操作请求和响应将显示在客户端控制台窗口中。 您会看到将除数为零报告为错误。 在客户端窗口中按 Enter 关闭客户端。

Add(15,3) = 18
Subtract(145,76) = 69
Multiply(9,81) = 729
FaultException<MathFault>: Math fault while doing division. Problem: divide by zero

Press <ENTER> to terminate client.

客户端通过捕获适当的 FaultException<MathFault> 异常来实现此功能。

catch (FaultException<MathFault> e)
{
    Console.WriteLine("FaultException<MathFault>: Math fault while doing " + e.Detail.operation + ". Problem: " + e.Detail.problemType);
    client.Abort();
}

默认情况下,意外异常的详细信息不会发送到客户端,以防止服务实现细节脱离服务的安全边界。 FaultContract 提供了一种方法来描述协定中的故障,并根据需要标记某些类型的异常,以便传输到客户端。 FaultException<T> 提供用于向使用者发送故障的运行时机制。

但是,在调试时查看服务故障的内部详细信息非常有用。 若要关闭前面所述的安全行为,可以指示服务器上每个未经处理的异常的详细信息应包含在发送到客户端的故障中。 这是通过将 IncludeExceptionDetailInFaults 设置为 true 完成的。 可以在代码中或配置中设置它,如以下示例所示。

<behaviors>
  <serviceBehaviors>
    <behavior name="CalculatorServiceBehavior">
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
</behaviors>

此外,通过将配置文件中的服务属性设置为 behaviorConfiguration “CalculatorServiceBehavior”,该行为必须与服务相关联。

若要在客户端上捕获这样的错误,必须捕获非泛型 FaultException

此行为应仅用于调试目的,不应在生产环境中启用。

设置、生成和运行示例

  1. 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。

  2. 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

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