C# Web Service異常處理的兩個常見問題
在.Net中實(shí)現(xiàn)Web服務(wù)時(shí),在Web服務(wù)接口中產(chǎn)生的任何用戶異常(非SoapException之外的異常)都被包裝為SoapException傳遞給客戶端,這使得難以采用通常的方式處理Web Service的異常。本文講述如何通過SoapExceptionHelper實(shí)現(xiàn)一致的異常處理。
C# Web Service異常處理問題
在.Net中實(shí)現(xiàn)Web服務(wù)時(shí),Web服務(wù)接口中產(chǎn)生的任何用戶異常(非SoapException之外的異常)都被包裝為SoapException傳遞給客戶端 ,用戶錯誤信息放置在SoapException的Message屬性中。
下面的例子演示了一個SoapException封裝的用戶異常信息。WebMethod接口TestException代碼拋出一個InvalidOperationException:
- [WebMethod]
- public void TestException() {
- throw new InvalidOperationException
- ("Invalid Operation.");
- }
WebMethod的客戶端將捕獲一個SoapException異常,Message消息如下:
其中Message消息包含一段“...-->[ 1 ]:[ 2 ] at ....”的信息,[1]為用戶異常類,[2]為用戶異常消息。而一個原始的SoapException(用new SoapException(...)的方式創(chuàng)建并拋出的異常)則沒有這些信息,下面是一個原始的SoapException消息:
遺憾的是,目前的SoapException并沒有提供更多直接的手段直接獲取原來的異常信息,唯一包含的用戶異常信息在Message字符串中,對于使用Web Service作為分布式機(jī)制的應(yīng)用系統(tǒng)來說是非常不方便的,調(diào)用者無法捕獲原來的異常,難以獲取用戶友好的異常信息。同時(shí),因?yàn)閃eb Service接口代理不再拋出原來的異常,應(yīng)用的開發(fā)者需要考慮兩套完全不同的異常處理機(jī)制,帶來了程序結(jié)構(gòu)的復(fù)雜性。
創(chuàng)建SoapException輔助類:SoapExceptionHelper 來解決C# Web Service異常處理
SoapExceptionHelper輔助類包含下列主要接口:
- IsUserException:是否是一個UserException
- UserException:返回原始的UserException
- Message:原始異常的錯誤消息。
- 獲得原始的用戶異常類和異常消息
- 通過正則表達(dá)式類我們可以獲得原始的用戶異常類和異常消息:
- ///
- /// 讀取UserException信息。
- ///
- private void ReadUserExceptionInfo() {
- //match user exception class
- System.Text.RegularExpressions.
- MatchCollection mc = Regex.Matches
- (soapException.Message, "---> ([^:]+):");
- if (mc.Count >= 1) {
- userExceptionClass = mc[0].Groups[1].Value;
- //match user exception message
- mc = Regex.Matches(soapException.
- Message, "---> [^:]+:(.*)\n");
- if (mc.Count > 0) UserExceptionMessage
- = mc[0].Groups[1].Value;
- }
- }
- 創(chuàng)建用戶異常實(shí)例
- UserException接口利用反射機(jī)制創(chuàng)建
- 一個原來的Exception類實(shí)例:
- ... ...
- Assembly callingAssemply = Assembly.
- GetCallingAssembly();
- Type exceptionType = GetExceptionType
- (callingAssemply); //獲得用戶異常類型定義
- Exception e = null;
- try {
- try {
- e = Activator.CreateInstance(exceptionType,
- new object[]{UserExceptionMessage},
- null) as Exception;
- }
- catch {}
- //if no exists constructor with message parameter,
- use no parameters constructor.
- if (e == null) e = Activator.CreateInstance
- (exceptionType) as Exception;
- }catch(Exception ex) {
- throw new SoapExceptionHelperException
- (userExceptionClass, ex);
- }
- return e;
創(chuàng)建用戶異常的問題
因?yàn)橛脩舢惓?赡芏x在不同的集成塊中,SoapExceptionHelper可能無法知道它的位置,無法正確的獲取C# Web Service異常處理類型,如一個與SoapExceptionHelper所在集成塊和調(diào)用集成塊(CallingAssembly)不再同一個引用范圍內(nèi)的異常類。SoapExceptionHelper如果無法創(chuàng)建原始異常的實(shí)例,就創(chuàng)建一個System.Exception對象實(shí)例。
為了創(chuàng)建真正的原始異常類,調(diào)用者可以在外部獲得實(shí)際的異常類型,并傳遞給SoapExceptionHelper,因?yàn)檎{(diào)用者可以明確的引用異常定義 所在的集成塊。示例如下:
- // 項(xiàng)目引用中引入異常定義所在的集成塊
- ...
- SoapExceptionHelper helper =
- new SoapExceptionHelper(se);
- Type type = Type.GetType(helper.
- UserExceptionClass, "<異常類所在的集成塊>");
- Exception e = helper.GetUserException(type);
- 如果外部沒有傳遞異常類型定義,
- SoapExceptionHelper嘗試以以下順序獲取異常類型定義:
- Executing Assembly
- Calling Assembly
- Referenced Assemblies (of Calling Assembly)
- System.Exception
- 使用SoapExceptionHelper
- 返回用戶友好的消息
- 使用SoapExceptionHelper顯示示例1中的錯誤消息:
- try {
- ... ... // call web method
- } catch (SoapException se){
- MessageBox.Show(new SoapExceptionHelper(se).
- Message) ; //show "Invalid Operation." string
【編輯推薦】