2009-01-24 28 views
13

Tôi đang sử dụng thẻ [System.Web.Script.Services.ScriptService] để sử dụng các dịch vụ web có thể gọi từ javascript phía máy khách. Những gì tôi cần là một cách đăng nhập toàn cầu bất kỳ ngoại lệ chưa được giải quyết nào trong các phương thức đó. Về phía khách hàng, tôi nhận được lỗi gọi lại và có thể tiến hành từ đó, nhưng tôi cần một phía máy chủ để ghi lại ngoại lệ.Đăng nhập ngoại lệ toàn cầu từ các dịch vụ ASP.NET [ScriptService]

Anh chàng tại url này: http://ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx

gợi ý rằng điều này không thể được thực hiện.

Điều đó có chính xác không? Tôi có nghiêm túc phải đi đến mọi webmethod duy nhất trong toàn bộ hệ thống và thử/nắm bắt các phương pháp như một toàn thể.

Trả lời

14

Bạn có thể sử dụng mô-đun HTTP để nắm bắt thông báo ngoại lệ, theo dõi ngăn xếp và loại ngoại lệ được phương pháp dịch vụ web đưa ra.

Đầu tiên một số nền tảng ...

  • Nếu một phương pháp dịch vụ web ném một ngoại lệ đáp ứng HTTP có một mã trạng thái 500.

  • Nếu lỗi tùy chỉnh được tắt thì dịch vụ web sẽ trả về ngoại lệ thông báo và theo dõi ngăn xếp cho ứng dụng khách dưới dạng JSON.Ví dụ:
    {"Message":"Exception message","StackTrace":" at WebApplication.HelloService.HelloWorld() in C:\Projects\Stackoverflow Examples\WebApplication\WebApplication\HelloService.asmx.cs:line 22","ExceptionType":"System.ApplicationException"}

  • Khi lỗi tùy chỉnh trên thì dịch vụ web trả về một thông điệp mặc định cho khách hàng và loại bỏ các ngăn xếp dấu vết và ngoại lệ loại:
    {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}

Vì vậy, những gì chúng ta cần làm là đặt lỗi tùy chỉnh cho dịch vụ web và cắm vào mô-đun HTTP:

  1. C hecks nếu yêu cầu là một phương pháp dịch vụ web
  2. Kiểm tra xem có ngoại lệ hay không - có nghĩa là mã trạng thái 500 đang được trả lại
  3. Nếu 1) và 2) là đúng thì nhận JSON ban đầu gửi cho khách hàng và thay thế bằng các JSON mặc định

Đoạn code dưới đây là một ví dụ của một mô-đun HTTP thực hiện điều này:

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() { } 
}

Module này sử dụng bộ lọc sau để ghi đè lên nội dung gửi đến khách hàng và lưu trữ các byte gốc (mà contai n thông báo ngoại lệ, theo dõi ngăn xếp và loại ngoại lệ):

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; } 
    } 
}

Phương pháp này yêu cầu phải tắt các lỗi tùy chỉnh cho dịch vụ web. Bạn có thể muốn giữ các lỗi tùy chỉnh cho phần còn lại của ứng dụng để các dịch vụ web phải được đặt trong một thư mục con. Lỗi tùy chỉnh có thể được tắt trong thư mục đó chỉ bằng cách sử dụng web.config ghi đè cài đặt gốc.

+0

Mặc dù tôi không tuân theo điều này trong dự án hiện tại của tôi, đây có lẽ là cách duy nhất để nắm bắt tất cả các lỗi này một cách đáng tin cậy. – Clyde

+0

Tôi đã cố gắng này, nhưng bằng cách nào đó bối cảnh của tôi.Response.Filter.length ném một ngoại lệ của loại 'System.NotSupportedException'. Nó không hoạt động. Tôi nghĩ nó rất gần, đầu ra của tôi chính xác như bạn đã nói. và tôi nhận được 500 mã trạng thái. – maxisam

-1

Trong ASP.Net, bạn có thể bắt tất cả các ngoại lệ được xử lý bằng cách sử dụng global error handler mặc dù bài đăng trên blog cho thấy điều này không hiệu quả nhưng bạn có thể thử nghiệm cách tiếp cận này để cố gắng sửa lại lỗi theo một cách nào đó?

Một ý tưởng khác là xem mã nguồn mở elmah (Mô-đun ghi nhật ký lỗi và trình xử lý) cho ASP.Net có thể giúp hoặc ai đó trong cộng đồng đó có ý tưởng.

+1

Vâng, tôi không chắc bạn có thực sự hiểu vấn đề không. Ngoại lệ * bị * bắt bởi mã dịch vụ tập lệnh ASP.NET - bị bắt trước khi tôi có cơ hội bắt được nó. Vì vậy, trình xử lý lỗi toàn cục không hoạt động. Khung này gửi một lỗi phía máy khách để tôi có thể hiển thị một thông báo, nhưng không có móc máy chủ – Clyde

+0

Tuy nhiên, liên kết elmah rất thú vị ... Tôi chắc chắn sẽ kiểm tra xem – Clyde

+0

Tôi là ELMAH thứ hai. Tôi sử dụng nó cho chính xác mục đích này. –

1

Tôi biết điều này không trả lời câu hỏi mỗi lần nói, nhưng tôi đã tự tìm kiếm một nhiệm vụ để tìm ra điều này và đưa tay trắng lên. Kết thúc gói mỗi cuộc gọi dịch vụ web trong một thử/nắm bắt, và bắt cuộc gọi logger lỗi của chúng tôi. Sucks, nhưng nó hoạt động.

3

Bạn chạy Thủ tục được lưu trữ trong phần cuối. Sau đó, đối với một biến duy nhất, nó trả về nhiều hơn 1 giá trị. Bởi vì điều đó, một xung đột xảy ra, và, lỗi này được ném ra.

Các vấn đề liên quan