Through WCF's basic exception handling pattern [previous], we know that, by default, the service side throws an exception (in this case, a faultexception exception) when it performs a service operation, and its associated error message is limited to the server-side visibility and is not passed to the client by WCF If the Servicedebug service behavior that opens the Includeexceptiondetailinfaults is applied to the corresponding service by declaring it (by applying the Servicebehaviorattrite attribute on the service type) or by the configured method. All details related to the exception will be sent to the client intact.
Both of these methods embody two extremes of anomalous propagation (Exception propagation) mechanisms, which are either completely masked to the client or exposed to the client for error details based on the exception thrown during the execution of the service operation. In a truly distributed system that is architected through WCF, we often need a compromise mechanism for exception propagation: Customizing server-side exception information. This allows the client to get an easily understandable error message, and to some extent avoids the disclosure of some sensitive information.
First, specify the error message directly via FaultException
For exceptions thrown in the execution of a service operation, if the definition of the service only wants the service's caller to get a custom error message text (string), what we do is actually very simple: throw a FaultException exception directly in the service operation. The exception object is created by a custom error message that is represented as a string. In the following code, the divide method of Calculaorservice validates the second parameter at the specified time, creates a faultexception if zero, and specifies the error message ("Dividend y cannot be zero!"). )。
1:using System.ServiceModel;
2:using Artech.WcfServices.Contracts;
3:namespace Artech.WcfServices.Services
4: {
5: [ServiceBehavior (Includeexceptiondetailinfaults = True)]
6: Public class Calculatorservice:icalculator
7: {
8: Public int Divide (int x, int y)
9: {
if (0 = y)
One: {
throw new FaultException ("Dividend y cannot be zero!");
: }
: Return x/y;
: }
: }
17:}
When the client invokes the service operation, passing in 0 as dividend will directly capture this exception that is thrown by the service-side definition (in fact, it goes through a series of operations such as serialization of Exception objects, message exchange, and deserialization of exception objects). The client-specific exception capture is reflected in the following procedure:
1:using System;
2:using System.ServiceModel;
3:using Artech.WcfServices.Contracts;
4:namespace Artech.WcfServices.Clients
5: {
6:class Program
7: {
8:static void Main (string[] args)
9: {
10:using (channelfactory<icalculator> ChannelFactory = new Channelfactory<icalculator> (
One: "CalculatorService"))
12: {
13:icalculator calculator = Channelfactory.createchannel ();
14:using (Calculator as IDisposable)
15: {
16:try
17: {
18:int result = Calculator. Divide (1, 0);
19:}
20:catch (FaultException ex)
21: {
22:console.writeline (ex. message);
: (Calculator as Icommunicationobject). Abort ();
24:}
25:}
26:}
27:}
28:}
29:}
Output results:
The divisor y cannot be zero!
Although in many cases, a FaultException exception that contains custom error messages is thrown directly through the service-side designation of a service operation, the client perceives the specific errors encountered and makes the necessary error and error correction. However, more often than not, we tend to define a type directly to describe the exception information. I personally prefer this type of category is the error detail type (Fault Detail type). The server creates the corresponding error type object based on the specific exception scenario, and based on the system.servicemodel.faultexception<tdetail> exception we mentioned above, where the generic type parameter is the exception detail type. In this process, there is also an important concept: the wrong contract (Fault Contract), and then we'll introduce the faultexception<tdetail> and the wrong contract.