2012-03-06 20 views
2

我有幾個Web方法可以用來調用Google Calendar API等外部服務,顯然這些方法可能非常脆弱。與JSON WebMethods的SoapExtension相當的功能是什麼?

不幸的是,我現在認識到,在這些方法上引發的任何錯誤都不會引發異常,導致Global.asax冒出來,這是在此應用程序中記錄錯誤的地方。

我已經看到了將方法封裝在try/catch中的建議,這是一種愚蠢的做法,因爲ASP.Net會默默吞下各種錯誤。

在試圖找到我已經看到了很多的參考解決SoapExtension,這正是我想做的事,但我要回JSON沒有被解僱。我真正想要的是一種像這樣捕捉錯誤的方法。

任何指針讚賞,我仍然無法理解ASP.Net團隊如何認爲,這樣默默地吞嚥這樣的錯誤是一個好主意。

因此,例如,像這樣的方法:

[WebMethod] 
    [ExceptionHandling] //can I write a handler like this to catch exceptions from JSON webservices? 
    static public void DeleteItem(string id) 
    { 
     var api = new GoogleCalendarAPI(User.InternalUser()); 
     api.DeleteEvent(id); 
     return "success"; 
    } 
+0

您的問題是,您應該使用WCF時使用舊技術。 WCF比ASMX更具可擴展性。 – 2012-03-06 14:48:58

+0

@JohnSaunders WCF很糟糕,在幾年內將會像死神一樣死去,它本身就是遺產。如果我可以使用任何我想用於MVC的東西,但是不能一夜之間重寫客戶端的傳統項目 – mattmanser 2012-03-06 14:54:32

+0

異常處理程序只能捕獲異常。如果這些例外被隱藏,那麼沒有例外可以處理。 – 2012-03-07 09:50:56

回答

6

對於JSON WebMethods並沒有相當於SoapExtension,並且在您的生產站點中打開自定義錯誤將導致返回給客戶端的通用錯誤消息,在服務器上不會產生錯誤。你不能規避這一點。

如果您使用類似ILSpy的東西檢查代碼,則無法將方法或類傳遞到頁面WebMethods,如SoapExtension。該錯誤被ASP.Net吞噬,因爲它會調用Web方法,您將得到的唯一通知是發送給客戶端的HTTP 500錯誤,並帶有一般性錯誤消息。

在4.0的WebMethods被調用本:

// System.Web.Script.Services.RestHandler 
internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData) 
{ 
    try 
    { 
     //snip irrelevant code 
     RestHandler.InvokeMethod(context, methodData, rawParams); 
    } 
    catch (Exception ex) 
    { 
     RestHandler.WriteExceptionJsonString(context, ex); 
    } 
} 

因此,如果調用你的方法拋出一個錯誤,它會調用與500的StatusCode下面的代碼,就沒有再扔在那裏,沒有別的你可以通過呼叫,除非我是盲目的,它只是默默吞下。即使你已經變得更糟自定義錯誤接通,這任何理智的人都會,它會完全模糊的成因:

// System.Web.Script.Services.RestHandler 
internal static void WriteExceptionJsonString(HttpContext context, Exception ex, int statusCode) 
{ 
    //snip code setting up response 
    context.Response.TrySkipIisCustomErrors = true; 
    using (StreamWriter streamWriter = new StreamWriter(context.Response.OutputStream, new UTF8Encoding(false))) 
    { 
     if (ex is TargetInvocationException) 
     { 
      ex = ex.InnerException; 
     } 
     if (context.IsCustomErrorEnabled) 
     { 
      streamWriter.Write(JavaScriptSerializer.SerializeInternal(RestHandler.BuildWebServiceError(AtlasWeb.WebService_Error, string.Empty, string.Empty))); 
     } 
     else 
     { 
      streamWriter.Write(JavaScriptSerializer.SerializeInternal(RestHandler.BuildWebServiceError(ex.Message, ex.StackTrace, ex.GetType().FullName))); 
     } 
     streamWriter.Flush(); 
    } 
} 

我無法看到它周圍的方式,看起來像的We​​bMethod還沒有準備好爲了生產代碼,恥辱。

0

它沒有這麼多,他們得到消失了,它更是他們得到傳遞出到調用客戶端。但是,由於您並不總是希望(或應該)揭示您的服務的這種私密細節,所以您可以防止錯誤冒出您的服務。這給他們留下了印象。

在try-catch中包裝內部細節是應對任何錯誤的最佳方法。在處理標準錯誤陷印的方法中。所以我覺得你想要的東西,如:

[WebMethod] 
static public string DeleteItem(string id) 
{ 
    try 
    { 
     var api = new GoogleCalendarAPI(User.InternalUser()); 
     api.DeleteEvent(id); 
     return "success"; 
    } 
    catch(Exception ex) 
    { 
     log.fatal(ex); 
     return "error"; 
    } 
} 

如果有任何拋出的try-catch它會被抓住內的異常。 ASP.Net不會干擾它,除非你所調用的方法已經被專門編碼。

編輯

如果GoogleCalendarAPI類依次調用的方法,如ExecuteWebServiceCall與捕獲該異常,那麼你就必須解析響應。我希望他們給你一些其他線索,如響應代碼,以指示錯誤狀態。然後,你可以將它包裝在一個異常中,拋出它被你的默認錯誤處理程序捕獲。

+0

我特意說我不想這樣做。有很多方法可以避免在WebMethod上發現嚴重的錯誤。由於js日曆控件配置錯誤,由於格式錯誤導致DateTime參數錯誤時怎麼辦?或者發生整數溢出?或者用戶在響應中傳遞了「asp.net禁止」字符?這將不會涉及這些。這是一個可怕的解決方案。 – mattmanser 2012-03-06 13:45:08

+0

他們都將被捕獲爲異常處理程序。你爲什麼不認爲他們會被抓到?從你的例子中,DateTime解析會拋出一個FormatException,它將被捕獲。 int將拋出一個被捕獲的overflowException。如果代碼拋出異常,則會被捕獲。在這個階段,ASP.net不能干預它,因爲它不知道發生了異常。它將不知道發生異常,直到異常被傳出該方法。 – 2012-03-07 09:37:31

+0

它如何幹擾?一個異常冒出了調用堆棧,直到它被處理。 Asp.net受到與框架其餘部分相同的異常處理規則的約束。我想我們在這裏談論的是不同的事情。我的回答並不愚蠢,因爲你已經顯示異常被困住了,所以你需要一個異常處理的替代方法。 – 2012-03-07 14:34:21