Is there a way to trap all errors in a AJAX-web service? Is there a way to trap all errors in a AJAX-web service? ajax ajax

Is there a way to trap all errors in a AJAX-web service?


As described in Capture all unhandled exceptions automatically with WebService there really is no good solution.

The reason that you cannot capture the HttpApplication.Error etc has to do with how the RestHandler has been implemented by the good folks at Microsoft. Specifically, the RestHandler explicitly catches (handles) the exception and writes out the exception details to the Response:

internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData){    try    {        NamedPermissionSet namedPermissionSet = HttpRuntime.NamedPermissionSet;        if (namedPermissionSet != null)        {            namedPermissionSet.PermitOnly();        }        IDictionary<string, object> rawParams = GetRawParams(methodData, context);        InvokeMethod(context, methodData, rawParams);    }    catch (Exception exception)    {        WriteExceptionJsonString(context, exception);    }}

To make matters worse, there is no clean extension point (that I could find) where you can change/extend the behavior. If you want to go down the path of writing your own IHttpHandler, I believe you will pretty much have to re-implement the RestHandler (or RestHandlerWithSession); regardless Reflector will be your friend.

For those that may choose to modify their WebMethods

If you are using Visual Studio 2008 or later, using Lambda expressions makes things not too bad (although not global/generic solution) in terms or removing duplicated code.

[WebMethod][ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]public String GetServerTime(){  return Execute(() => DateTime.Now.ToString());}public T Execute<T>(Func<T> action){  if (action == null)    throw new ArgumentNullException("action");  try  {    return action.Invoke();  }  catch (Exception ex)  {    throw; // Do meaningful error handling/logging...  }}

Where Execute can be implemented in a subclass of WebService or as an extension method.

UPDATE: Reflection Evil

As mentioned in my origional answer, you can abuse reflection to get what you want... specifically you can create your own HttpHandler that makes use of the internals of the RestHandler to provide an interception point for capturing exception details. I have include an "unsafe" code example below to get you started.

Personally, I would NOT use this code; but it works.

namespace WebHackery{  public class AjaxServiceHandler : IHttpHandler  {    private readonly Type _restHandlerType;    private readonly MethodInfo _createHandler;    private readonly MethodInfo _getRawParams;    private readonly MethodInfo _invokeMethod;    private readonly MethodInfo _writeExceptionJsonString;    private readonly FieldInfo _webServiceMethodData;    public AjaxServiceHandler()    {      _restHandlerType = typeof(ScriptMethodAttribute).Assembly.GetType("System.Web.Script.Services.RestHandler");      _createHandler = _restHandlerType.GetMethod("CreateHandler", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(HttpContext) }, null);      _getRawParams = _restHandlerType.GetMethod("GetRawParams", BindingFlags.NonPublic | BindingFlags.Static);      _invokeMethod = _restHandlerType.GetMethod("InvokeMethod", BindingFlags.NonPublic | BindingFlags.Static);      _writeExceptionJsonString = _restHandlerType.GetMethod("WriteExceptionJsonString", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(HttpContext), typeof(Exception) }, null);      _webServiceMethodData = _restHandlerType.GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);    }    public bool IsReusable    {      get { return true; }    }    public void ProcessRequest(HttpContext context)    {      var restHandler = _createHandler.Invoke(null, new Object[] { context });      var methodData = _webServiceMethodData.GetValue(restHandler);      var rawParams = _getRawParams.Invoke(null, new[] { methodData, context });      try      {        _invokeMethod.Invoke(null, new[] { context, methodData, rawParams });      }      catch (Exception ex)      {        while (ex is TargetInvocationException)          ex = ex.InnerException;        // Insert Custom Error Handling HERE...        _writeExceptionJsonString.Invoke(null, new Object[] { context, ex});      }    }  }}


This a good question. I've had this problem in the web app that I work on. I'm afraid my solution wasn't smart in any way. I simply wrapped in the code in each web service method in a try/catch and returned an object which indicated whether the method had run successfully or not. Fortunately my app doesn't have a massive number of web service calls so I can get away will this. I appreciate it's not a good solution if you're doing loads of web service calls.


Have you taken a look at WCF Web API?This is currently in beta, but it is already being used in several live sites.Exposing json/xml rest api's is very easy.In it you can create your own HttpErrorHandler derived class to handle errors. It is a very clean solution. Might be worth taking a closer look for you. Migrating any existing service should also be straightforward. Hope it helps!