Asp.net

從 ASP.NET 全域記錄異常小號criptService小號Cr一世p噸小號和rv一世C和ScriptService服務

  • December 14, 2012

我正在使用

$$ 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 模組:

  1. 檢查請求是否針對 Web 服務方法
  2. 檢查是否拋出異常 - 即返回狀態碼 500
  3. 如果 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 在該目錄中關閉自定義錯誤。

引用自:https://stackoverflow.com/questions/475189