我使用了一些网络方法来调用某些外部服务,例如Google Calendar API,显然这些方法非常脆弱。
不幸的是,我现在意识到在这些方法上抛出的任何错误都不会导致异常冒泡到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 :(得分:6)
对于JSON WebMethods,没有等效的SoapExtension
,并且在生产站点中打开自定义错误将导致返回到客户端的一般错误消息,服务器上不会出现任何错误。你不能绕过这个。
如果使用ILSpy之类的东西检查代码,则无法通过方法或类来传递像SoapExtension
这样的WebMethods。 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);
}
}
因此,如果调用你的方法会抛出一个错误,它将调用以下代码,statusCode为500,那里没有重新抛出而你没有其他任何东西可以调用,所以除非我是盲目的,否则它会被静默吞噬。更糟糕的是,如果你打开了自定义错误,任何理智的人都会这样做,它会完全模糊原因:
// 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();
}
}
我无法看到解决方法,看起来WebMethod还没有为生产代码做好准备,感到羞耻。
答案 1 :(得分: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捕获异常),那么您必须解析响应。我希望他们给你一些其他线索,比如响应代码,以指示错误状态。然后你可以将它包装在一个Exception中,抛出它让它被你的默认错误处理程序捕获。