WCF服務創建與拋出強類型SOAP Fault


原創地址:http://www.cnblogs.com/jfzhu/p/4060666.html                 

轉載請注明出處

 

前面的文章《WCF服務的異常消息》中介紹過,如果WCF Service發生異常時,Service會將異常序列化為SOAP Fault並發送給客戶端。

默認情況下,出於安全原因,WCF Service中未處理的異常的詳細信息不會包括在發送給客戶的SOAP Fault里,你只能看到一個通用的SOAP Fault(“The server was unable to process the request due to an internal error.”)。在調試程序的時候,如果想在SOAP Fault中包含異常的詳細信息,可以修改服務器的配置文件。

<behaviors>
  <serviceBehaviors>
    <behavior name="includeExceptionDetails">
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>


 

SOAP Fault是XML格式,與平台無關。通常一個SOAP Fault包含以下節點

(1) faultcode

(2) faultstring

(3) detail

 

Detail節點可以用來包括自定義XML信息。

 

WCF Service在發生異常時應拋出FaultException或FaultException<T>,而不應該拋出.NET Exception,出於以下兩個原因:

(1)未處理的.NET Exception會使服務器與客戶端之間的channel變為Fault狀態,繼而導致client proxy無法使用。

(2).NET Exception只能被.NET平台理解,而FaultException與平台無關。如果想跨平台使用,需要使用FaultException。

 

下面還是以中《WCF服務的異常消息》的例子來分別演示如何拋出與處理FaultException與強類型的FaultException<T>。

 

(一)使用FaultException

IDemoService.cs:

using System.ServiceModel;

namespace WCFDemo 
{    
    [ServiceContract(Name = "IDemoService")] 
    public interface IDemoService 
    { 
        [OperationContract]        
        int Divide(int numerator, int denominator); 
    } 
}

 

DemoService.cs:

using System; 
using System.ServiceModel; 
using System.ServiceModel.Activation;

namespace WCFDemo 
{ 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class DemoService : IDemoService 
    { 
        public int Divide(int numerator, int denominator) 
        { 
            if (denominator == 0) 
            { 
                throw new FaultException("Denominator cannot be ZERO!", new FaultCode("DivideByZeroFault")); 
            } 
            return numerator / denominator;           
        } 
    } 
}

 

client:

private void buttonCalculate_Click(object sender, EventArgs e) 
{ 
    try 
    {                
        textBoxResult.Text = demoServiceClient.Divide(Convert.ToInt32(textBoxNumerator.Text), Convert.ToInt32(textBoxDenominator.Text)).ToString(); 
    } 
    catch (FaultException fault) 
    { 
        MessageBox.Show(fault.Code + " - " + fault.Message); 
    } 
}

 

 

image

image

 

SOAP Fault XML

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
  <s:Body> 
    <s:Fault> 
      <faultcode>s:DivideByZeroFault</faultcode> 
      <faultstring xml:lang="en-US">Denominator cannot be ZERO!</faultstring> 
    </s:Fault> 
  </s:Body> 
</s:Envelope>

 

 

(二)使用強類型FaultException<T>

(1)創建一個自定義SOAP Fault類

DivideByZeroFault.cs:

using System.Runtime.Serialization;

namespace WCFDemo 
{ 
    [DataContract] 
    public class DivideByZeroFault 
    { 
        [DataMember] 
        public string Error { get; set; }

        [DataMember] 
        public string Detail { get; set; } 
    } 
}

 

(2) 在Service方法上使用FaultContractAttribute來指示哪個操作可以使用哪個Fault

IDemoService.cs:

using System.ServiceModel;

namespace WCFDemo 
{    
    [ServiceContract(Name = "IDemoService")] 
    public interface IDemoService 
    { 
        [FaultContract(typeof(DivideByZeroFault))]         [OperationContract]        
        int Divide(int numerator, int denominator); 
    } 
}

 

DemoService.cs:

using System; 
using System.ServiceModel; 
using System.ServiceModel.Activation;

namespace WCFDemo 
{ 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class DemoService : IDemoService 
    { 
        public int Divide(int numerator, int denominator) 
        { 
            try 
            { 
                return numerator / denominator; 
            } 
            catch (DivideByZeroException ex) 
            { 
                DivideByZeroFault fault = new DivideByZeroFault(); 
                fault.Error = ex.Message; 
                fault.Detail = "Denominator cannot be ZERO!"; 
                throw new FaultException<DivideByZeroFault>(fault); 
            } 
        } 
    } 
}

 

client:

private void buttonCalculate_Click(object sender, EventArgs e) 
{ 
    try 
    {                
        textBoxResult.Text = demoServiceClient.Divide(Convert.ToInt32(textBoxNumerator.Text), Convert.ToInt32(textBoxDenominator.Text)).ToString(); 
    } 
    catch (FaultException<DemoServiceReference.DivideByZeroFault> fault) 
    { 
        MessageBox.Show(fault.Detail.Error + " - " + fault.Detail.Detail); 
    } 
}

 

 

image

image

 

返回的SOAP Fault XML:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
  <s:Body> 
    <s:Fault> 
      <faultcode>s:Client</faultcode> 
      <faultstring xml:lang="en-US">The creator of this fault did not specify a Reason.</faultstring> 
      <detail> 
        <DivideByZeroFault xmlns="http://schemas.datacontract.org/2004/07/WCFDemo" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
          <Detail>Denominator cannot be ZERO!</Detail> 
          <Error>Attempted to divide by zero.</Error> 
        </DivideByZeroFault> 
      </detail> 
    </s:Fault> 
  </s:Body> 
</s:Envelope>

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM