2009-01-24 7 views
13

Używam znacznika [System.Web.Script.Services.ScriptService] do korzystania z usług WWW wywoływanych po stronie klienta po stronie javascript. Potrzebuję sposobu globalnego rejestrowania wszelkich nieobsługiwanych wyjątków w tych metodach. Po stronie klienta otrzymuję komunikat o błędzie zwrotnym i mogę kontynuować pracę, ale potrzebuję przechwycenia po stronie serwera, aby zarejestrować wyjątek.Globalne rejestrowanie wyjątków z usług ASP.NET [ScriptService]

Facet pod tym adresem: http://ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx

sugeruje, że nie można tego zrobić.

Czy to jest dokładne? Czy naprawdę muszę przejść do każdego webmethod w całym systemie i spróbować/złapać metodę jako całość.

Odpowiedz

14

Możesz użyć modułu HTTP do przechwycenia komunikatu wyjątku, śledzenia stosu i typu wyjątku, który jest generowany przez metodę usługi sieciowej.

Najpierw niektóre tła ...

  • Jeśli metoda serwis internetowy zgłasza wyjątek odpowiedź HTTP posiada kod statusu 500.

  • Jeśli niestandardowe błędy są wyłączone, to serwis internetowy zwróci komunikat o wyjątku: i ślad stosu do klienta jako JSON.Na przykład:
    {"Message":"Exception message","StackTrace":" at WebApplication.HelloService.HelloWorld() in C:\Projects\Stackoverflow Examples\WebApplication\WebApplication\HelloService.asmx.cs:line 22","ExceptionType":"System.ApplicationException"}

  • Kiedy niestandardowe błędy są na to serwis internetowy zwraca komunikat domyślny do klienta i usuwa stos śledzenia i wyjątku typ:
    {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}

Więc co my trzeba ustawić wyłączone niestandardowe błędy dla usługi internetowej i podłączyć moduł HTTP, który:

  1. C sprawdza, czy żądanie dotyczy metody usługi sieciowej. Sprawdza, czy został zgłoszony wyjątek - to znaczy, że zwracany jest kod stanu wynoszący
  2. Jeśli 1) i 2) są prawdziwe, to należy uzyskać oryginalny JSON, który byłby wysyłane do klienta i zastąpić ją domyślną JSON

poniższy kod jest przykładem modułu HTTP, które wykonuje to:

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

moduł ten wykorzystuje następujący filtr nadpisać zawartość wysłanego do klienta i do przechowywania oryginalnych bajtów (które zawierają n komunikatu wyjątku, śledzenia stosu i typu wyjątku):

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

Ta metoda wymaga wyłączenia błędów niestandardowych w usługach internetowych. Prawdopodobnie chcesz zachować niestandardowe błędy dla reszty aplikacji, aby usługi sieciowe były umieszczone w podkatalogu. Błędy niestandardowe można wyłączyć w tym katalogu tylko za pomocą pliku web.config, który zastępuje ustawienie nadrzędne.

+0

Chociaż nie śledzę tego w moim bieżącym projekcie, prawdopodobnie jest to jedyny sposób, aby niezawodnie wykryć wszystkie te błędy. – Clyde

+0

Próbowałem tego, ale jakoś mój context.Response.Filter.length rzucił wyjątek typu "System.NotSupportedException". To po prostu nie działa. Myślę, że jest bardzo blisko, moje wyniki są dokładnie takie, jak powiedziałeś. i mam 500 kodów statusu. – maxisam

-1

W ASP.Net możliwe jest przechwycenie wszystkich uruchomionych wyjątków obsługiwanych przy użyciu global error handler, mimo że post na blogu sugeruje, że to nie działa, ale można eksperymentować z tym podejściem próbując w jakiś sposób obalić błąd?

Innym pomysłem byłoby obejrzenie open source (Error Logging Modules and Handlers) dla ASP.Net, które mogą pomóc lub ktoś w tej społeczności może mieć pomysł.

+1

Tak, nie jestem pewien, czy naprawdę zrozumiałeś problem. Wyjątek * jest przechwytywany przez kod usługi skryptowej ASP.NET - złapany zanim będę miał szansę go złapać. Globalna obsługa błędów nie działa. Framework wysyła błąd po stronie klienta, więc mogę wyświetlić komunikat, ale nie ma haka na serwerze. – Clyde

+0

Jednak link elmah jest interesujący ... Na pewno to sprawdzę – Clyde

+0

Powiedziałbym ELMAH. Używam tego dokładnie w tym celu. –

1

Wiem, że to nie jest odpowiedź na pytanie, powiedzmy, ale poszedłem na własną misję chwilę, aby to znaleźć i wznowiłem z pustymi rękami. Zakończyłem pakowanie każdej usługi sieciowej w try/catch, a catch wywołuje nasz rejestr błędów. Jest do bani, ale działa.

3

Uruchamiasz procedurę przechowywaną w backend. Następnie dla pojedynczej zmiennej zwraca więcej niż 1 wartość. Z tego powodu występują konflikty i ten błąd jest zgłaszany.

Powiązane problemy