The WCF client and service-side framework systems work together to make it possible for developers to handle exception handling in the way we are familiar with: throwing an exception during service operation execution (FaultException), catching an exception when invoking a service, and completely feeling the "distributed" presence, as is typical of "local "The operation is general. In order to achieve this effect, WCF has done a lot for us internally.
Message exchange is the only way for WCF to communicate, the message is not only the carrier of the normal service invocation request and reply, the exception that the server throws, even the metadata of the service is transmitted to the client through the form of the message. Therefore, the transformation between the exception and the message is the core of the entire exception handling system, and the WCF exception handling framework is focused on accomplishing this function.
We can simply describe the functional implementation of the WCF exception handling framework: The WCF server serializes the thrown FaultException exception and eradicate the message's SOAP specification (SOAP 1.1 or soap 1.2) and the Ws-addressing specification (ws-addressing 2004 and Ws-addressing 1.0) generate fault messages. The channel layer is passed through, after a series of channels, the fault message is returned to the client by means of the transport layer, and the client channel layer is deserialized after receiving the fault message and processing accordingly. The result of deserialization is the rebuilding of the FaultException, where WCF eventually throws the reconstructed FaultException exception, and for the eventual developer, it feels like the faultexception thrown by the server is captured directly by the client. As we have said in the previous section, WCF does not directly convert between faultexception and fault messages, but with the help of the Messagefault intermediate object. The right-hand figure reflects the flow of errors (Fault) throughout the WCF exception handling process.
Through the introduction of medium, we know that the core object of serialization and deserialization of FaultException is faultformatter, and understanding the implementation principle of WCF's entire exception-handling framework first needs to know how Faultformatter is created.
First, how Faultformatter is created?
Both the WCF server and the client require a Faultformatter object for serialization and deserialization of the FaultException exception object, and now we describe how the Faultformatter object was created on both the server side and the client.
1, Faultformatter (dispatchfaultformatter) in the service side how to be created
Faultformatter is created at the time of service boarding at the service end. Specifically, during ServiceHost initialization, WCF creates an appropriate endpoint distributor (EndpointDispatcher) for each endpoint of the service. For each endpoint distributor that is created, it has a corresponding distribution runtime (DispatchRuntime). DispatchRuntime is the core of the entire WCF runtime framework, and a series of objects and components are referenced by it to achieve control over the entire message distribution and operation execution behavior. (The implementation process of the entire service hosted within the WCF Server framework is described in detail in the 7th chapter of the WCF Technical Profiling (Volume 1).) )
During DispatchRuntime initialization, WCF creates a series of DispatchOperation objects based on the description of the service. The DispatchOperation object can be seen as the representation of a service operation at runtime, and ultimately the execution of the service operation is done through it. Specifically, WCF obtains the contract description (ContractDescription) of the current endpoint, traversing each operation description (operationdescription) to create the corresponding dispatchoperation. The relationship between ServiceEndpoint, ContractDescription, and operationdescription is defined by the following type of code at a glance.
1:public class ServiceEndpoint
2: {
3: //other Members
4: Public contractdescription Contract {get;}
5:}
6:public class ContractDescription
7: {
8: //other Members
9: Public operationdescriptioncollection Operations {get;}
10:}
11:public class OperationDescription
12: {
: //other Members
: Public faultdescriptioncollection faults {get;}
15:}
For the type of operationdescription that is described as an operation, There is a collection property of type System.ServiceModel.Description.FaultDescriptionCollection that is related to the topic of this chapter: Faults, which represents a collection of all the error descriptions associated with this operation. Each element of the collection is a System.ServiceModel.Description.FaultDescription object, and the Faultdescription object is reflected on the Faultcontractattribute attribute applied to the operation. The definition of faultdescription is as follows, which is exactly the same as the structure definition of faultcontractattribute.
1:public class Faultdescription
2: {
3: //other Members
4: Public string Action {get; internal set;}
5: Public Type Detailtype {get; set;}
6: Public bool Hasprotectionlevel {get;}
7: Public string Name {get; set;}
8: Public string Namespace {get; set;}
9: Public protectionlevel ProtectionLevel {get; set;}
10:}
When the WCF server runtime creates a corresponding dispatchoperation based on an action description, the Faultformatter object is created based on the description of the error, declaring the type to be idispatchfaultformatter.
1:public Sealed class DispatchOperation
2: {
3: //other Members
4:public synchronizedcollection<faultcontractinfo> Faultcontractinfos
5: {get;}
6: Internal idispatchfaultformatter faultformatter {get; set;}
7:}
You will also see from the code snippet above that there is a type of synchronizedcollection<faultcontractinfo> in addition to an internal property faultformatter Collection properties: Faultcontractinfos. The System.ServiceModel.Dispatcher.FaultContractInfo object that acts as a collection element represents the information associated with the error contract, which matches the faults property of the operation description (OperationDescription). In fact, Faultcontractinfo contains only two information that implements serialization: the error detail type and the action, which can be seen from the definition of Faultcontractinfo:
1:public class Faultcontractinfo
2: {
3: //other Members
4: Public string Action {get;}
5: Public Type Detail {get;}
6:}