Asp.net
從 ASP.NET 全域記錄異常小號criptService小號Cr一世p噸小號和rv一世C和ScriptService服務
我正在使用
$$ System.Web.Script.Services.ScriptService $$標記以使用可從客戶端 JavaScript 呼叫的 Web 服務。我需要的是一種在這些方法中全域記錄任何未處理異常的方法。在客戶端,我收到錯誤回調並可以從那裡繼續,但我需要一個伺服器端擷取來記錄異常。 這個網址的人:http: //ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx
表明這是無法做到的。
那準確嗎?我真的必須去整個系統中的每一個 webmethod 並嘗試/擷取整個方法。
您可以使用 HTTP 模組來擷取 Web 服務方法拋出的異常消息、堆棧跟踪和異常類型。
首先是一些背景…
- 如果 Web 服務方法引發異常,則 HTTP 響應的狀態程式碼為 500。
- 如果自定義錯誤關閉,則 Web 服務將異常消息和堆棧跟踪以 JSON 形式返回給客戶端。例如:
{"Message":"Exception message","StackTrace":" at WebApplication.HelloService.HelloWorld() in C:\Projects\Stackoverflow Examples\WebApplication\WebApplication\HelloService.asmx.cs:line 22","ExceptionType":"System.ApplicationException"}- 當自定義錯誤出現時,Web 服務會向客戶端返回預設消息並刪除堆棧跟踪和異常類型:
{"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}所以我們需要做的是為 Web 服務設置自定義錯誤並插入一個 HTTP 模組:
- 檢查請求是否針對 Web 服務方法
- 檢查是否拋出異常 - 即返回狀態碼 500
- 如果 1) 和 2) 為真,則獲取將發送到客戶端的原始 JSON 並將其替換為預設 JSON
下面的程式碼是執行此操作的 HTTP 模組的範例:
using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Web; public class ErrorHandlerModule : IHttpModule { public void Init(HttpApplication context) { context.PostRequestHandlerExecute += OnPostRequestHandlerExecute; context.EndRequest += OnEndRequest; } static void OnPostRequestHandlerExecute(object sender, EventArgs e) { HttpApplication context = (HttpApplication) sender; // TODO: Update with the correct check for your application if (context.Request.Path.StartsWith("/HelloService.asmx") && context.Response.StatusCode == 500) { context.Response.Filter = new ErrorHandlerFilter(context.Response.Filter); context.EndRequest += OnEndRequest; } } static void OnEndRequest(object sender, EventArgs e) { HttpApplication context = (HttpApplication) sender; ErrorHandlerFilter errorHandlerFilter = context.Response.Filter as ErrorHandlerFilter; if (errorHandlerFilter == null) { return; } string originalContent = Encoding.UTF8.GetString( errorHandlerFilter.OriginalBytesWritten.ToArray()); // If customErrors are Off then originalContent will contain JSON with // the original exception message, stack trace and exception type. // TODO: log the exception } public void Dispose() { } }該模組使用以下過濾器覆蓋發送給客戶端的內容並儲存原始字節(包含異常消息、堆棧跟踪和異常類型):
public class ErrorHandlerFilter : Stream { private readonly Stream _responseFilter; public List OriginalBytesWritten { get; private set; } private const string Content = "{\"Message\":\"There was an error processing the request.\"" + ",\"StackTrace\":\"\",\"ExceptionType\":\"\"}"; public ErrorHandlerFilter(Stream responseFilter) { _responseFilter = responseFilter; OriginalBytesWritten = new List(); } public override void Flush() { byte[] bytes = Encoding.UTF8.GetBytes(Content); _responseFilter.Write(bytes, 0, bytes.Length); _responseFilter.Flush(); } public override long Seek(long offset, SeekOrigin origin) { return _responseFilter.Seek(offset, origin); } public override void SetLength(long value) { _responseFilter.SetLength(value); } public override int Read(byte[] buffer, int offset, int count) { return _responseFilter.Read(buffer, offset, count); } public override void Write(byte[] buffer, int offset, int count) { for (int i = offset; i < offset + count; i++) { OriginalBytesWritten.Add(buffer[i]); } } public override bool CanRead { get { return _responseFilter.CanRead; } } public override bool CanSeek { get { return _responseFilter.CanSeek; } } public override bool CanWrite { get { return _responseFilter.CanWrite; } } public override long Length { get { return _responseFilter.Length; } } public override long Position { get { return _responseFilter.Position; } set { _responseFilter.Position = value; } } }此方法需要為 Web 服務關閉自定義錯誤。您可能希望為應用程序的其餘部分保留自定義錯誤,因此應將 Web 服務放置在子目錄中。只能使用覆蓋父設置的 web.config 在該目錄中關閉自定義錯誤。