定义和指定错误Defining and Specifying Faults

SOAP 错误可将错误情况信息从服务传达到客户端,在双工情况下,还可以以互操作方式从客户端传达到服务。SOAP faults convey error condition information from a service to a client and, in the duplex case, from a client to a service in an interoperable way. 此主题讨论何时并且如何自定义错误内容并指定可以返回错误的操作。This topic discusses when and how to define custom fault content and specify which operations can return them. 有关服务或双工客户端如何发送这些故障以及客户端或服务应用程序如何处理这些故障的详细信息,请参阅发送和接收故障For more information about how a service, or duplex client, can send those faults and how a client or service application handles these faults, see Sending and Receiving Faults. 有关 Windows 通信基础 (WCF) 应用程序中的错误处理的概述,请参阅在合同和服务中指定和处理错误For an overview of error handling in Windows Communication Foundation (WCF) applications, see Specifying and Handling Faults in Contracts and Services.

概述Overview

声明的 SOAP 错误是指其中的某个操作具有 System.ServiceModel.FaultContractAttribute 的错误,该属性指定自定义 SOAP 错误类型。Declared SOAP faults are those in which an operation has a System.ServiceModel.FaultContractAttribute that specifies a custom SOAP fault type. 未声明的 SOAP 错误是指那些未在相应操作的协定中指定的错误。Undeclared SOAP faults are those that are not specified in the contract for an operation. 本主题帮助您识别这些错误情况并为您的服务创建一个错误协定,当收到自定义 SOAP 错误时,客户端可以用它正确地处理这些错误情况。This topic helps you identify those error conditions and create a fault contract for your service that clients can use to properly handle those error conditions when notified by custom SOAP faults. 基本任务依次为:The basic tasks are, in order:

  1. 定义服务的客户端应该知道的错误情况。Define the error conditions that a client of your service should know about.

  2. 为这些错误情况定义 SOAP 错误的自定义内容。Define the custom content of the SOAP faults for those error conditions.

  3. 标记您的操作,以便以 WSDL 向客户端公开这些操作引发的特定 SOAP 错误。Mark your operations so that the specific SOAP faults that they throw are exposed to clients in WSDL.

定义客户端应该知道的错误情况Defining Error Conditions That Clients Should Know About

SOAP 错误是公开描述的、传达特定操作的错误信息的消息。SOAP faults are publicly described messages that carry fault information for a particular operation. 由于它们是同其他操作消息一起以 WSDL 描述的,因此客户端应该知道它们且希望在调用某个操作时处理这样的错误。Because they are described along with other operation messages in WSDL, clients know and, therefore, expect to handle such faults when invoking an operation. 但是,由于 WCF 服务是在托管代码中编写的,因此确定托管代码中的哪些错误条件要转换为错误并返回到客户端,因此您有机会将服务中的错误条件和错误与正式错误分开您与客户的对话。But because WCF services are written in managed code, deciding which error conditions in managed code are to be converted into faults and returned to the client provides you the opportunity to separate error conditions and bugs in your service from the formal error conversation you have with a client.

例如,下面的代码示例演示一个采用两个整数并返回另一个整数的操作。For example, the following code example shows an operation that takes two integers and returns another integer. 这里可引发若干个异常,因此设计错误协定时,必须确定哪些是客户端最重要的错误情况。Several exceptions can be thrown here, so when designing the fault contract, you must determine which error conditions are important for your client. 在这种情况下,服务应该删除 System.DivideByZeroException 异常。In this case, the service should detect the System.DivideByZeroException exception.

[ServiceContract]  
public class CalculatorService  
{  
    [OperationContract]
    int Divide(int a, int b)  
    {  
      if (b==0) throw new Exception("Division by zero!");  
      return a/b;  
    }  
}  
<ServiceContract> _
Public Class CalculatorService
    <OperationContract> _
    Public Function Divide(a As Integer, b As Integer) As Integer
        If b = 0 Then Throw New DivideByZeroException("Division by zero!")
        Return a / b
    End Function
End Class

在上面的示例中,该操作可返回一个特定的除以零的自定义 SOAP 错误、可返回一个特定于数学运算但包含特定的除以零信息的自定义错误、可为若干个不同错误情况返回多个错误,或根本不返回 SOAP 错误。In the preceding example the operation can either return a custom SOAP fault that is specific to dividing by zero, a custom fault that is specific to math operations but that contains information specific to dividing by zero, multiple faults for several different error situations, or no SOAP fault at all.

定义错误情况的内容Define the Content of Error Conditions

将某个错误情况标识为可有效地返回一个自定义 SOAP 错误后,下一步是定义该错误的内容并确保内容结构可以被序列化。Once an error condition has been identified as one that can usefully return a custom SOAP fault, the next step is to define the contents of that fault and ensure that the content structure can be serialized. 上面的代码示例演示的是特定于 Divide 运算的一个错误,如果 Calculator 服务上还存在其他运算,则单个自定义 SOAP 错误可通知客户端所有计算器错误情况,包括 DivideThe code example in the preceding section shows an error specific to a Divide operation, but if there are other operations on the Calculator service, then a single custom SOAP fault can inform the client of all calculator error conditions, Divide included. 下面的代码示例演示如何创建一个自定义 SOAP 错误 MathFault,它可以报告使用所有数学运算(包括 Divide)时产生的错误。The following code example shows the creation of a custom SOAP fault, MathFault, which can report errors made using all math operations, including Divide. 当该类可以指定一个操作(Operation 属性)和一个描述问题的值(ProblemType 属性)时,该类和这些属性必须被序列化以便以自定义 SOAP 错误的形式传输到客户端。While the class can specify an operation (the Operation property) and a value that describes the problem (the ProblemType property), the class and these properties must be serializable to be transferred to the client in a custom SOAP fault. 因此,使用 System.Runtime.Serialization.DataContractAttributeSystem.Runtime.Serialization.DataMemberAttribute 属性 (Attribute),以使该类型及其属性 (Property) 可序列化和尽可能可互操作。Therefore, the System.Runtime.Serialization.DataContractAttribute and System.Runtime.Serialization.DataMemberAttribute attributes are used to make the type and its properties serializable and as interoperable as possible.

// Define a math fault data contract
[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; }
    }
}
' Define a math fault data contract
<DataContract([Namespace]:="http://Microsoft.ServiceModel.Samples")> _
Public Class MathFault

    Private m_operation As String
    Private m_problemType As String

    <DataMember()> _
    Public Property Operation() As String

        Get

            Return m_operation

        End Get

        Set(ByVal value As String)

            m_operation = value

        End Set

    End Property

    <DataMember()> _
    Public Property ProblemType() As String

        Get

            Return m_problemType

        End Get

        Set(ByVal value As String)

            m_problemType = value

        End Set

    End Property

End Class

有关如何确保数据可序列化的详细信息,请参阅在服务协定中指定数据传输For more information about how to ensure your data is serializable, see Specifying Data Transfer in Service Contracts. 有关提供的序列化支持的列表,System.Runtime.Serialization.DataContractSerializer请参阅数据协定序列化器支持的类型For a list of the serialization support that System.Runtime.Serialization.DataContractSerializer provides, see Types Supported by the Data Contract Serializer.

标记操作以建立错误协定Mark Operations to Establish the Fault Contract

定义了一个将作为自定义 SOAP 错误的一部分返回的可序列化数据结构后,最后一步是将操作协定标记为引发该类型的一个 SOAP 错误。Once a serializable data structure that is returned as part of a custom SOAP fault is defined, the last step is to mark your operation contract as throwing a SOAP fault of that type. 为此,可以使用 System.ServiceModel.FaultContractAttribute 属性并传递构造的自定义数据类型的类型。To do this, use the System.ServiceModel.FaultContractAttribute attribute and pass the type of the custom data type that you have constructed. 下面的代码示例演示如何使用 FaultContractAttribute 属性将 Divide 运算指定为可以返回一个 MathFault 类型的 SOAP 错误。The following code example shows how to use the FaultContractAttribute attribute to specify that the Divide operation can return a SOAP fault of type MathFault. 现在也可以将其他基于数学的运算指定为可以返回 MathFaultOther math-based operations can now also specify that they can return a MathFault.

[OperationContract]
[FaultContract(typeof(MathFault))]
int Divide(int n1, int n2);
<OperationContract()> _
<FaultContract(GetType(MathFault))> _
Function Divide(ByVal n1 As Integer, ByVal n2 As Integer) As Integer

可以将某个操作指定为返回一个以上的自定义错误,方法为使用一个以上的 FaultContractAttribute 属性标记该操作。An operation can specify that it returns more than one custom fault by marking that operation with more than one FaultContractAttribute attribute.

下一步,为了在操作实现中实现故障协定,在主题"发送和接收故障"中介绍了这一步骤。The next step, to implement the fault contract in your operation implementation, is described in the topic Sending and Receiving Faults.

SOAP、WSDL 和互操作性的注意事项SOAP, WSDL, and Interoperability Considerations

在某些情况下,特别是与其他平台进行互操作时,控制错误在 SOAP 消息中的显示方式或在 WSDL 元数据中对它的描述方式可能会十分重要。In some circumstances, especially when interoperating with other platforms, it may be important to control the way a fault appears in a SOAP message or the way it is described in the WSDL metadata.

FaultContractAttribute 属性 (Attribute) 有一个 Name 属性 (Property),可以控制在元数据中为该错误生成的 WSDL 错误元素名称。The FaultContractAttribute attribute has a Name property that allows control of the WSDL fault element name that is generated in the metadata for that fault.

根据 SOAP 标准,一个错误可有一个 Action、一个 Code,以及一个 ReasonAccording to the SOAP standard, a fault can have an Action, a Code, and a Reason. ActionAction 属性控制。The Action is controlled by the Action property. Code 属性和 Reason 属性是 System.ServiceModel.FaultException 类的两个属性,该类是泛型 System.ServiceModel.FaultException<TDetail> 的父类。The Code property and Reason property are both properties of the System.ServiceModel.FaultException class, which is the parent class of the generic System.ServiceModel.FaultException<TDetail>. Code 属性包含一个 SubCode 成员。The Code property includes a SubCode member.

在访问生成错误的非服务时,存在某些限制。When accessing non-services that generate faults, certain limitations exist. WCF 仅支持架构描述且与数据协定兼容的详细信息类型的故障。WCF supports only faults with detail types that the schema describes and that are compatible with data contracts. 例如,如上所述,WCF 不支持在其详细信息类型中使用 XML 属性的故障,也不支持详细信息部分中具有多个顶级元素的错误。For example, as mentioned above, WCF does not support faults that use XML attributes in their detail types, or faults with more than one top-level element in the detail section.

另请参阅See also