《WCF技术内幕》翻译25:第2部分_第5章_消息:创建一个消息(下)之MessageFault

简介:

MessageSOAP Fault老徐备注1

Message类型定义了一些用来创建表示SOAP Fault消息对象的工厂方法。SOAP Fault是 SOAP消息的一种形式,它用来表示错误信息。在SOAP规范(1.1 和1.2)对于消息体内容,并且某些时候,关于 SOAP消息头块的规定都存在差别。Message是对于SOAP消息的CLR抽象,Message可以表示SOAP Fault,和表示一个SOAP消息一样。本节会描述一些SOAP Fault的基本概念和创建表示SOAP Fault消息的基本类型以及如何创建一个表示SOAP Fault的Message实例。

SOAP Fault 剖析

SOAP Fault遵守SOAP规范(1.1 和1.2)。根本上,SOAP1.1 Fault包含一个SOAP body,body里包装了一个必须的faultcode 老徐备注2faultstring元素,还有一个可选的faultactor和faultdetail元素。为了避免重复叙述这些规范,你可以在这里 http://www.w3.org/TR/soap11找到更多的可选择元素的消息规范。在更高层次上,faultcode表示一个标识符,接受者和发送者可以用来辨别错误 SOAP1.1规范,定义了一个faultcode的小集合,但是程序可以定义自己使用的唯一的faultcode。Faultstring表示一种人工可读的faultcode,它不是要给接收程序(除非你想吧Faultstring显示给用户)。Faultcode是一个描述错误来源的URI。
SOAP Fault 从SOAP 1.1到SOAP 1.2发生了很大的变化。因为SOAP 1.2是建立在Infoset上的, SOAP 1.2 Fault本质上是由一个信息条目集合组成。除了这些变化,SOAP Fault组成部分的名字也做了修改和扩展,以包含更多的描述信息。SOAP 1.2规定SOAP Fault应该包含一个必须的Code和Reason(原因),一个可选的Node、Role或Detail(详细信息)。何时增加这些信息的详细规定可以在这里查看: http://www.w3.org/TR/soap12-part1/#soapfault。通常来说,Code是发生错误的标识符,而且也允许使用子code表示更细粒度的信息。SOAP 1.2定义了一些Code,并且允许程序定义自己的Code。Reason便是人工可读的错误解释信息。Node表示产生错误的消息参与者。Role信息表示的是SOAP错误产生时,消息参与者的角色。Detail是给其它消息参与者准备的错误信息。
SOAP 1.1 和1.2 Fault,抛去他们的区别,在他们描述的信息类型上还是很相似的。两者都规定了错误代码的标签,人工可读的错误描述信息,导致SOAP Fault的消息参与者信息和错误的其它信息。 为这目的, WCF 定义了一个表示SOAP 1.1和SOAP 1.2 Fault System.ServiceModel.Channels.MessageFault 类型。在我们学习如何表示SOAP 1.1 和SOAP 1.2描述的SOAP Fault之前,我们先来看看 MessageFault类型如何概括归纳SOAP Fault的。

MessageFault

The  MessageFault type is a way to describe error information in a SOAP-version-agnostic manner. Keeping in mind that WCF has a highly layered architecture, the  MessageFault type provides tremendous flexibility when processing SOAP messages and optionally generating exceptions.
MessageFault类型可以描述各种 SOAP版本的错误信息。记住WCF拥有更高层的架构,MessageFault类型在处理SOAP消息或者产生异常的时候提供了巨大的灵活性。
创建一个 MessageFault对象  像许多WCF里的别的类型一样,MessageFault是个定义了几个工厂方法的抽象类型。这些工厂方法接受表示SOAP Fault里存储信息的参数。此外MessageFault同样定义了接受产生SOAP Fault的消息参与者的标识作为参数。值得注意的是, MessageFault定义了一个工厂方法接受一个Message作为参数。这个方法在WCF接收一个SOAP Fault  Message,并需要传递这个错误信息到别的 WCF基础结构部分进行处理的时候,非常有用。
System.ServiceModel.FaultCode类型表示 faultcode信息。这个类型定义了几个工厂方法作为构造函数。所有的构建方法云系使用子code。FaultCode类型上的工厂方法,会自动产生发送者和接收者的错误代码(像SOAP 1.1 和SOAP 1.2定义的一样)。
System.ServiceModel.FaultReason类型表示 faultreason。最简单的情况,一个构造函数接受一个String字符串作为参数。String表示人工可读的错误信息。因为人说的语言不同(Microsoft .NET开发人员也不会说一个语言), FaultReason类型定义了构造函数和方法允许程序嵌入多种版本的String和适当的基于不同文化的描述信息。
除了那一个MessageFault定义的工厂方法,其它的都接受一个FaultCode 和FaultReason类型作为参数。因此,这些类型必须在 MessageFault创建之前实例化,除了从Message创建MessageFault。几个工厂方法也接受Object作为参数,这个表示额外的错误信息。对于Message工厂方法里的Object参数,它们必须支持序列化(更多序列化的内容在第9章)。这个参数的存在带来一个问题,”我该使用什么类型作为参数?”因为System.Exception 是可序列化的,你或许会传递一个Exception参数。我强烈建议你打消这个想法。我更愿意自定义一个传递错误信息给其它消息参与者的类型。正如我们将会在第 9章看到的一样,这给契约带来了一个变化。
MessageFault  创建Message   我们一旦创建了MessageFault,我们可以调用Message上定义的别的工厂方法来创建一个Message。下面的代码演示了如何使用FaultCode、FaultReason和Object去创建一个MessageFault,也包括如何从MessageFault创建一个Message。
 
static void Main() {
// create a Receiver Fault Code
FaultCode faultCode = FaultCode.CreateReceiverFaultCode("MyFaultCode",
                                                                                                                    "urn:MyNS");
// create a meaningful FaultReason
FaultReason faultReason = new FaultReason("The value must be > 10");
    
// create an object that represents the SOAP Fault detail
SomeFaultDetail faultDetail = new SomeFaultDetail("Contoso", "SomeApp");
    
// create a MessageFault
MessageFault messageFault = MessageFault.CreateFault(faultCode,
                                                                                                             faultReason,
                                                                                                             faultDetail);
    
// Build a Message from the MessageFault, passing the MessageVersion
CreateAndShowMessage(messageFault, MessageVersion.Soap11WSAddressing10);
CreateAndShowMessage(messageFault, MessageVersion.Soap12WSAddressing10);
}
    
private static void CreateAndShowMessage(MessageFault messageFault,
                                                                                 MessageVersion version) {
// actually create the Message object w/version info
Message message = Message.CreateMessage(version,
                                                            messageFault,
                                                                                    "urn:SomeFaultAction");
// show the contents of the Message
Console.WriteLine("{0}\n", message.ToString());
}
    
// a serializable type for storing Fault detail information
[Serializable]
sealed class SomeFaultDetail {
String companyName;
String applicationName;
DateTime? dateOccurred;
    
internal SomeFaultDetail(String companyName, String applicationName) {
        this.companyName = companyName;
        this.applicationName = applicationName;
        //this.dateOccurred = null;
        this.dateOccurred = DateTime.Now;
}
}
运行代码,产生以下结果:
 
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
        xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
        <a:Action s:mustUnderstand="1">
            urn:SomeFaultAction
        </a:Action>
</s:Header>
<s:Body>
        <s:Fault>
            <faultcode xmlns:a="urn:MyNS">a:MyFaultCode</faultcode>
            <faultstring xml:lang="en-US">The value must be > 10</faultstring>
            <detail>
                <Program.SomeFaultDetail xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MessageFaults">
                    <applicationName>SomeApp</applicationName>
                    <companyName>Contoso</companyName>
                    <dateOccurred>2006-06-14T12:34:44.52325-04:00</dateOccurred>
                </Program.SomeFaultDetail>
            </detail>
        </s:Fault>
</s:Body>
</s:Envelope>
    
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
        xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
        <a:Action s:mustUnderstand="1">
            urn:SomeFaultAction
        </a:Action>
</s:Header>
<s:Body>
        <s:Fault>
            <s:Code>
                <s:Value>s:Receiver</s:Value>
                <s:Subcode>
                    <s:Value xmlns:a="urn:MyNS">a:MyFaultCode</s:Value>
                </s:Subcode>
            </s:Code>
            <s:Reason>
                <s:Text xml:lang="en-US">The value must be > 10</s:Text>
            </s:Reason>
            <s:Detail>
                <Program.SomeFaultDetail xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MessageFaults">
                    <applicationName>SomeApp</applicationName>
                    <companyName>Contoso</companyName>
                    <dateOccurred>2006-06-14T12:34:44.52325-04:00</dateOccurred>
                </Program.SomeFaultDetail>
            </s:Detail>
        </s:Fault>
</s:Body>
</s:Envelope>
这段代码展示的最显著的特性就是MessageFault如何做到消息版本独立。第一次调用 CreateAndShowMessage传递的参数是MessageFault和 MessageVersion.Soap11WSAddressing10,结果是一个SOAP 1.1 Fault。第2次调用CreateAndShowMessage传递的参数是同一个 MessageFault,但是MessageVersion变为MessageVersion.Soap12WSAddressing10。结果就是一个SOAP 1.2 Fault。
前面代码展示了如何从MessageFault创建一个Message。Message定义了一个接受一个 MessageFault参数工厂方法和几个接受一个FaultCode的工厂方法。Message的这些工厂方法允许程序创建一个MessageFault或FaultCode标志错误。然后传递这个对象给 WCF基础结构里的其它层去产生一个Message对象。
注释:这看起来像个小功能,但是确带来了巨大好处。作用上,MessageFault 类型的MessageVersion版本兼容能力允许在WCF基础结构的另外部分来决定SOAP消息版本。换句话说,WCF基础结构里只有一层为了传输需要知道SOAP消息版本,因此创建了一个热拔插和可扩展的框架。
 
 

老徐备注

1. SOAP Fault  元素
来自  SOAP  消息的错误消息被携带于  Fault  元素内部。
如果已提供了  Fault  元素,则它必须是  Body  元素的子元素。在一条  SOAP  消息中, Fault  元素只能出现一次。
SOAP   Fault  元素用于下列子元素:
子元素
描述
<faultcode>
供识别故障的代码
<faultstring>
可供人阅读的有关故障的说明
<faultactor>
有关是谁引发故障的信息
<detail>
存留涉及  Body  元素的应用程序专用错误信息
 
2 SOAP Fault Codes
在下面定义的  faultcode  值必须用于描述故障时的  faultcode  元素中:
错误
描述
VersionMismatch
SOAP Envelope  元素的无效命名空间被发现
MustUnderstand
Header  元素的一个直接子元素(带有设置为  "1"   mustUnderstand  属性)无法被理解。
Client
消息被不正确地构成,或包含了不正确的信息。
Server
服务器有问题,因此无法处理进行下去。
参考:http://www.w3school.com.cn/soap/soap_fault.asp



 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/318588 ,如需转载请自行联系原作者
相关文章
|
10月前
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
9月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
39 0
|
9月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
66 0