We have an older ASP.NET WebForms application which performs AJAX request by using jQuery $.ajax()
calls on the client side, calling static methods in the page code-behind decorated with [WebMethod]
attributes.
If an unhandled exception occurs within the WebMethod, it does not fire the Application_Error
event and is thus not picked up by our error logger (ELMAH). This is well known and not a problem - we have all WebMethod code wrapped in try-catch blocks with exceptions being manually logged to ELMAH.
However, there is one case that has me stumped. If malformed Json is posted to the WebMethod URL, it throws an exception before entering our code, and I can't find any way to trap this.
e.g. this WebMethod signature
[WebMethod]
public static string LeWebMethod(string stringParam, int intParam)
Normally called with a Json payload like:
{"stringParam":"oh hai","intParam":37}
I tried a test using Fiddler to edit the payload to the malformed Json:
{"stringParam":"oh hai","intPara
And got the following ArgumentException
error response from JavaScriptObjectDeserializer
sent to the client (this is in a simple test app running locally with no custom errors):
{"Message":"Unterminated string passed in. (32): {\"stringParam\":\"oh hai\",\"intPara","StackTrace":" at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeMemberName()\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at
System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at
System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at
System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.ArgumentException"}
It's still not firing the Application_Error
event, and it never enters our code so we can't log the error ourselves.
I found a similar question which got a pointer to the blog post "How to create a global exception handler for a Web Service" but that appears to only be valid for SOAP webservices, not AJAX GETs/POSTs.
Is there some similar way to attach a custom handler in my situation?