In [previous], we presented the SOAP fault and FaultException exceptions in the context of message exchange and programming respectively. During service execution, we throw the faultexception exception manually, and the WCF server-side framework serializes the exception object and eventually generates fault messages. When the WCF client framework introduces the fault message, it does the opposite: parse and deserialize the fault message, regenerate and throw the faultexception exception. The WCF framework has done so much "behind-the-scenes" work for us, making it possible for developers to fully use the written generic. NET application pattern: Throw the corresponding exception in the wrong place, and make the corresponding exception capture and processing for the potential error method call. Therefore, the core function of the WCF exception handling framework is to implement the conversion between FaultException exception and fault message, and then we will focus on this topic.
The link between faultexception anomaly and fault message: Messagefault
For the WCF exception handling framework, which itself does not directly convert between FaultException exception and fault message, it is done through another object as an intermediary, which is the focus of this section: Messagefault. Message (Fault), Messagefault, and faultexception transform each other through "triangle" relationships as depicted in Figure 1.
Figure 1 Message (Fault), message, and faultexception "triangle" transformation relationship
Before the message is introduced Messagefault, let's look at the definition of Messagefault. Messagefault defined under the namespace System.ServiceModel.Channels, the following code is the definition of messagefault.
1:public Abstract class Messagefault
2: {
3://other Members
4:public static Messagefault createfault (Message message, int maxbuffersize);
5:public static Messagefault Createfault (faultcode code, Faultreason reason);
6:public static Messagefault Createfault (faultcode Code, string reason);
7:public static Messagefault Createfault (faultcode code, Faultreason Reason, object detail);
8:public static Messagefault Createfault (faultcode code, Faultreason Reason, object detail, Xmlobjectserializer seria Lizer);
9:public static Messagefault Createfault (faultcode code, Faultreason Reason, object detail, Xmlobjectserializer seria Lizer, string actor);
10:public static Messagefault Createfault (faultcode code, Faultreason Reason, object detail, Xmlobjectserializer Seri Alizer, string actor, string node);
11:
12:public T getdetail<t> ();
13:public T getdetail<t> (Xmlobjectserializer serializer);
14:public XmlDictionaryReader getreaderatdetailcontents ();
15:
16:public void WriteTo (XmlDictionaryWriter writer, envelopeversion version);
17:public void WriteTo (XmlWriter writer, envelopeversion version);
18:
19:public Virtual string Actor {get;}
20:public abstract faultcode Code {get;}
21:public abstract bool Hasdetail {get;}
22:public bool Ismustunderstandfault {get;}
23:public Virtual string Node {get;}
24:public abstract Faultreason Reason {get;}
25:}
From the Messagefault definition given above, it can be seen that its property members and FaultException, and the 5 child elements of the SOAP fault want to match: Code, Reason, Node, Actor (for soap The role element of the SOAP fault in the 1.2 specification, in SOAP 1.1, is named actor). The other element detail can be obtained through two generic methods getdetail<t>. Because this operation requires deserialization of the error detail object, you need to specify the serializer for the error detail type, which is DataContractSerializer by default. The attribute Ismustunderstandfault describes whether this error was caused by the recognition of a SOAP header failure, and in fact, it corresponds to the ispredefinedfault of the FaultCode, which has a predefined code, Ismustunderstandfault returns True.
by Messagefault Numerous Createfault static methods, we can specify the 5 elements that make up the SOAP fault in different combinations. If you specify an error detail object, you need to specify the serializer that matches it to serialize and deserialize it. The two overloaded Wirteto method serializes the Messagefault and writes the serialized XML to the corresponding "stream" through XmlDictionaryWriter or XmlWriter.
Because versions of the different SOAP specifications (SOAP 1.1 and SOAP 1.2) have different rules for the structure of the message fault, All calls to the Wirteto need to explicitly specify the write based on that version (SOAP version is represented by Envelopeversion). In the following example code, we create a Messagefault object that is written in two different XML files for SOAP 1.1 and SOAP 1.2, respectively. The reader can carefully discern how much difference the resulting message fault is.
1:using System.Collections.Generic;
2:using System.Diagnostics;
3:using System.IO;
4:using System.Runtime.Serialization;
5:using System.ServiceModel;
6:using System.ServiceModel.Channels;
7:using System.Text;
8:using System.Xml;
9:namespace Messagefaultdemos
10: {
11:class Program
12: {
13:static void Main (string[] args)
14: {
15:faultcode code = Faultcode.createsenderfaultcode (New FaultCode ("Calculationerror", "http://www.artech.com/ "));
16:ilist<faultreasontext> reasontexts = new list<faultreasontext> ();
17:reasontexts.add (New Faultreasontext ("The input parameter is invalid!", "en-us"));
18:reasontexts.add (New Faultreasontext ("input parameter not valid!", "ZH-CN"));
19:faultreason reason = new Faultreason (reasontexts);
20:
21:calculationerror detail = new Calculationerror ("Divide", "dividend y cannot be zero!");
22:messagefault fault = messagefault.createfault (code, Reason, detail, new DataContractSerializer (typeof (Calc Ulationerror)), "Http://http://www.artech.com/calculatorservice", "Http://http://www.artech.com/calculationcenter");
23:
24:string fileName1 = @ "Fault.soap11.xml";
25:string fileName2 = @ "Fault.soap12.xml";
26:writefault (Fault, fileName1, ENVELOPEVERSION.SOAP11);
27:writefault (Fault, fileName2, ENVELOPEVERSION.SOAP12);
28:}
29:
30:static void Writefault (Messagefault fault, String fileName, envelopeversion version)
31: {
32:using (FileStream stream = new FileStream (FileName, FileMode.Create, FileAccess.Write))
33: {
34:using (XmlDictionaryWriter writer = Xmldictionarywriter.createtextwriter (stream, Encoding.UTF8, false) )
35: {
36:fault. WriteTo (writer, version);
37:process.start (FileName);
38:}
39:}
40:}
41:}
42:}