根据参考资料,内部
RestHandler.ExecuteWebServiceCall方法捕获所有抛出的异常,
GetRawParams并将它们简单地写入响应流,这就是为什么
Application_Error不对其进行调用的原因:
internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData) { try { ... IDictionary<string, object> rawParams = GetRawParams(methodData, context); InvokeMethod(context, methodData, rawParams); } catch (Exception ex) { WriteExceptionJsonString(context, ex); }}我能想到的唯一解决方法是创建一个输出过滤器来拦截并记录输出:
public class PageMethodExceptionLogger : Stream{ private readonly HttpResponse _response; private readonly Stream _baseStream; private readonly MemoryStream _capturedStream = new MemoryStream(); public PageMethodExceptionLogger(HttpResponse response) { _response = response; _baseStream = response.Filter; } public override void Close() { if (_response.StatusCode == 500 && _response.Headers["jsonerror"] == "true") { _capturedStream.Position = 0; string responseJson = new StreamReader(_capturedStream).ReadToEnd(); // TODO: Do the actual logging. } _baseStream.Close(); base.Close(); } public override void Flush() { _baseStream.Flush(); } public override long Seek(long offset, SeekOrigin origin) { return _baseStream.Seek(offset, origin); } public override void SetLength(long value) { _baseStream.SetLength(value); } public override int Read(byte[] buffer, int offset, int count) { return _baseStream.Read(buffer, offset, count); } public override void Write(byte[] buffer, int offset, int count) { _baseStream.Write(buffer, offset, count); _capturedStream.Write(buffer, offset, count); } public override bool CanRead { get { return _baseStream.CanRead; } } public override bool CanSeek { get { return _baseStream.CanSeek; } } public override bool CanWrite { get { return _baseStream.CanWrite; } } public override long Length { get { return _baseStream.Length; } } public override long Position { get { return _baseStream.Position; } set { _baseStream.Position = value; } }}在Global.asax.cs(或HTTP模块)中,将过滤器安装在
Application_PostMapRequestHandler:
protected void Application_PostMapRequestHandler(object sender, EventArgs e){ HttpContext context = HttpContext.Current; if (context.Handler is Page && !string.IsNullOrEmpty(context.Request.PathInfo)) { string contentType = context.Request.ContentType.Split(';')[0]; if (contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase)) { context.Response.Filter = new PageMethodExceptionLogger(context.Response); } }}


