Như được mô tả trong Capture all unhandled exceptions automatically with WebService thực sự không có giải pháp tốt.
Lý do bạn không thể chụp HttpApplication.Error, v.v. có liên quan đến cách RestHandler đã được thực hiện bởi những người tốt ở Microsoft. Cụ thể, RestHandler bắt một cách rõ ràng (xử lý) các ngoại lệ và viết ra các chi tiết ngoại lệ đối với đáp ứng:
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);
}
}
Để làm cho vấn đề tồi tệ hơn, không có điểm mở rộng sạch (mà tôi có thể tìm thấy), nơi bạn có thể thay đổi/mở rộng hành vi. Nếu bạn muốn đi xuống con đường viết IHttpHandler của riêng bạn, tôi tin rằng bạn sẽ phải thực hiện lại phần còn lại của RestHandler (hoặc RestHandlerWithSession); bất kể Reflector sẽ là bạn của bạn.
Đối với những người có thể chọn để thay đổi WebMethods họ
Nếu bạn đang sử dụng Visual Studio 2008 hoặc mới hơn, sử dụng biểu thức Lambda làm cho mọi thứ không quá xấu (mặc dù không phải toàn cầu/generic giải pháp) về hoặc loại bỏ nhân đôi mã.
[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...
}
}
Nơi thực thi có thể được triển khai trong lớp con của WebService hoặc làm phương pháp mở rộng.
UPDATE: Reflection Ác
Như đã đề cập trong câu trả lời origional của tôi, bạn có thể lạm dụng phản ánh để có được những gì bạn muốn ... đặc biệt bạn có thể tạo HttpHandler của riêng bạn mà làm cho việc sử dụng bên trong của RestHandler để cung cấp một điểm chặn để ghi lại các chi tiết ngoại lệ. Tôi đã bao gồm một ví dụ mã "không an toàn" bên dưới để giúp bạn bắt đầu.
Cá nhân, tôi sẽ KHÔNG sử dụng mã này; nhưng nó đã có tác dụng.
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});
}
}
}
}
Có bất kỳ linh hoạt trong yêu cầu mà bạn không thể sửa đổi các phương pháp web? –
Vâng, vâng - miễn là tôi không phải bao quanh tất cả chúng trong các khối try/catch khổng lồ .. Nếu giải pháp được sạch sẽ, sau đó tôi mở cửa cho nó. –
Tôi có một giải pháp yêu cầu khối Thử và bắt một dòng. Bạn có thể cải thiện nó để loại bỏ hoàn toàn thử/nắm bắt, tôi chưa đào sâu. Bạn muốn đăng nó? –