本文目的
通過閱讀本文,您能理解以下的知識
1) WCF中存在哪幾種異常處理方式?
2) 各種異常處理所適用的應用場合?
3) WCF中常見的異常類型?
4) 代碼不騙人,用示例來演示效果,加深印象
本文適合的讀者
本文適合WCF的初學者,但要求對WCF有一些了解,並實現過簡單的服務/客戶端。
WCF中存在哪幾種異常處理方式?
WCF定義了幾種異常處理模型,它們分別如下:
1) 缺省模式
2) 包含詳細信息模式
3) 自定義異常消息模式
各種異常處理所適用的應用場合?
1) 缺省模式
缺省情況下,服務端發生異常,客戶端會得到一個缺省的Exception,但這個Exception實例中並不包括詳細的異常信息。只是告訴客戶端服務端不能正常工作。在服務器和客戶端模式的程序中,有些情況下,服務啟是不能完全信賴客戶端的,比如浏覽器和web服務器之間,為了防止非法的客戶端從異常消息中獲取服務端的比較詳細的信息,使得心懷叵測之人有機可乘,所以服務啟對於異常 返回通常會比較模糊。WCF也采用了這種做法,缺省情況下,它返回給客戶端的異常只告知我出錯了,但不告訴人家他哪裡錯了。這通常應用於客戶端來源不明的生產環境,以此保護服務程序。
2) 包含詳細信息模式
如果想消息更友好一些,可以通過IncludeExceptionDetailInFaults=True來設置返回具體的異常信息,這樣就能告訴客戶端服務出錯了,並指出錯誤出在哪裡。在程序開發階段或者有些應用場合,客戶端是受信任的,為了讓客戶端能更詳盡的了解服務端到底出了什麼問題,WCF也支持發送詳細的錯誤消息給客戶端,這更有利於應用程序調試。而返回詳細異常有兩種方法:第一種:通過在服務端的配置文件中設置:<serviceDebug includeExceptionDetailInFaults="False" />,第二種方式為通過在代碼中指定:[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
3) 自定義異常消息模式
在WCF中,還支持更詳細的異常消息,它通過自定義的異常消息FaultMessage來傳達更多的內容。WCF采用通用的Soap Fault來處理異常,並提供了FaultException和FaultException<FaultMessage>兩個類型來描述和操作異常。
WCF中常見的異常類型?
WCF包括三種常見類型的異常:
1) 通訊異常,這通常是因為鏈路的原因,比如服務沒有啟動,網絡阻塞等。這類異常是CommunicationException或者其派生類
2) 狀態異常,這類異常通常是與上文提到的實例模式相關的,當訪問了一個已經銷毀的服務器對象時便會引發此類型的異常,它們通常是ObjectDisposedException
3) 服務異常,由服務端根據具體的業務邏輯觸發,通常是FaultException 值得注意的是當拋出服務異常的時候,不同的實例模式的處理方式有所不同:
PerSession:這種模式下,拋出異常,服務實例將銷毀,客戶端拋出FaultException,客戶端代理對象無法繼續使用
PerCall:這種模式下,拋出異常,服務實例也將銷毀。客戶端代理對象無法繼續使用
Single:這種模式下,拋出異常,服務實例會照舊運行。客戶端代理無法繼續使用。
代碼不騙人,用示例來演示效果,加深印象
本文所實現的實例非常簡單,目的就是想驗證一下各種異常處理方式下的不同表現。
1) 缺省模式
在示例中,我們這樣拋出異常
public string GetWelcomeInfo([ParaAtt(CanSetNull=false)] string name)
{
ParameterInfo para = MethodInfo.GetCurrentMethod().GetParameters()[0];
ParaAtt att = ParaAtt.GetCustomAttribute(para, typeof(ParaAtt)) as ParaAtt;
if (!att.CanSetNull && name == null)
{
throw new Exception("參數不能設置為null");
}
return "Hello," + name;
}
而此時,我們運行客戶端,可以發現如下的運行結果:
從結果可以看出,缺省情況下,雖然客戶端跑出了異常,但這些異常消息是不呈獻給客戶端的
2) 包含詳細信息模式
將服務端配置文件中的<serviceDebug includeExceptionDetailInFaults="True" />,再次啟動,此時客戶端不但能收到和上圖一致的跟蹤堆棧信息,不同的是異常消息也會呈現給客戶端
3) 自定義異常消息模式
這種模式是異常處理中相對最難的,因為它更加靈活,我們首先定義一個用於表示錯誤消息的數據契約ExceptionMsg,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace Jillzhang.Wcf.ExContracts
{
[DataContract]
public class ExceptionMsg
{
/**//// <summary>
/// 異常消息文本
/// </summary>
[DataMember]
public string Message { get; set; }
/**//// <summary>
/// 異常編碼
/// </summary>
[DataMember]
public string ErrorCode { get; set; }
}
}
在定義操作的時候,我們可以指定返回的異常消息的類型,方法如下:
[OperationContract]
[FaultContract(typeof(ExceptionMsg))]
int Devide(int x, int y);
運行實例程序,可以得到如下的結果:
我們可以用tcpTrace來跟蹤下異常消息,有關如何跟蹤WCF的Soap消息,前面文章WCF從理論到實踐二:決戰紫禁之巅 有所描述。本文講述例外一種方法用於跟蹤basicHttpBinding,為此我們要准備一款工具,Trace Utility,它是Microsoft SOAP Toolkit Version 3中的一個工具,利用它可以清晰地看到SoapMessage,方式如下:打開Trace Utility,選擇菜單項File-Formated Trace,在接下來的對話框中填寫要監聽的端口和服務的端口,如下圖所示:
點擊確定後,將原來客戶端端中的服務地址由
更改為
啟動,便可以在Trace Utility中跟蹤到SoapMessage,如下:
- <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
- <s:Body>
- <s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="zh-CN">The creator of this fault did not specify a Reason.</faultstring>
- <detail>
- <ExceptionMsg xmlns="http://schemas.datacontract.org/2004/07/Jillzhang.Wcf.ExContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ErrorCode>001</ErrorCode>
<Message>除數不能為0</Message>
</ExceptionMsg>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
另外很多人不清楚如何調試跟蹤WCF應用程序,特別是想從客戶段跟蹤到服務中,可以通過以下步驟來完成:
本文配套源碼