Как описано в Capture all unhandled exceptions automatically with WebService, на самом деле нет хорошего решения.
Причина, по которой вы не можете захватить HttpApplication.Error и т. Д., Связана с тем, как RestHandler был реализован хорошими людьми в Microsoft. В частности, RestHandler явно ловит (ручки) исключение и выписывает детали исключения в ответ:
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);
}
}
В довершение, нет чистой точки расширения (что я мог бы найти), где вы можете изменить/расширить поведение. Если вы хотите пойти по пути написания собственного IHttpHandler, я верю, что вам придется переустановить RestHandler (или RestHandlerWithSession); независимо от Reflector будет вашим другом.
Для тех, которые могут выбрать, чтобы изменить их WebMethods
Если вы используете Visual Studio 2008 или более поздней версии, с помощью лямбда-выражений делает вещи не так уж плохо (хотя и не глобальный/общее решение) в терминах или удаление дублируется код.
[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...
}
}
Где Execute может быть реализовано в подклассе WebService или в качестве метода расширения.
UPDATE: Отражение Зла
Как упоминалось в моем оригинальный ответ, вы можете злоупотреблять отражение, чтобы получить то, что вы хотите ... конкретно вы можете создать свой собственный HttpHandler, который использует внутренностями RestHandler для предоставить точку перехвата для получения сведений об исключении. У меня есть пример «небезопасного» кода ниже, чтобы вы начали.
Лично я бы не использовал этот код; но он работает.
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});
}
}
}
}
Есть ли гибкость в требование о том, что вы не можете изменять веб-методы? –
Ну, да - пока мне не нужно окружать все их в гигантских блоках try/catch. Если решение чистое, то я открыт для него. –
У меня есть решение, для которого требуется блок Try и одна строка Catch. Вы можете улучшить его, чтобы полностью избавиться от попытки/улова, я не вырыл это глубоко. Хотите опубликовать? –