Globalnie loguj wyjątki z ASP.NET [ScriptService] usługi
Używam [systemu.Www.Scenariusz.Usługi.ScriptService] tag do korzystania z usług internetowych wywołanych z javascript po stronie klienta. Potrzebuję sposobu globalnego rejestrowania wszelkich nieobsługiwanych wyjątków w tych metodach. Po stronie klienta dostaję oddzwonienie o błędzie i mogę kontynuować stamtąd, ale potrzebuję przechwytywania po stronie serwera, aby zarejestrować wyjątek.
Facet pod tym adresem url: http://ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx
Sugeruje, że to to niemożliwe.
Czy to prawda? Czy naprawdę muszę przejść do każdego webmethod w całym systemie i spróbować / złapać metodę jako całość.
4 answers
Możesz użyć modułu HTTP do przechwytywania wiadomości wyjątku, śledzenia stosu i typu wyjątku, które są rzucane przez metodę usługi internetowej.
Najpierw trochę tła...Jeśli metoda usługi internetowej rzuca wyjątek, odpowiedź HTTP ma kod stanu 500.
Jeśli błędy niestandardowe są wyłączone, to sieć usługa zwróci wyjątek wiadomość i stos trace 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"}
Gdy błędy niestandardowe są włączone następnie usługa internetowa zwraca domyślną wiadomość do klienta i usuwa stos Typ śledzenia i wyjątku:
{"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}
Więc to, co musimy zrobić, to ustawić niestandardowe błędy dla usługi internetowej i podłączyć moduł HTTP, który:
- sprawdza, czy żądanie dotyczy metody usługi internetowej
- sprawdza, czy wyjątek został wyrzucony-tzn. zwracany jest kod stanu 500
- Jeśli 1) i 2) są prawdziwe, to pobierz oryginalny JSON, który zostanie wysłany do klient i zastąp go domyślnym JSON
Poniższy kod jest przykładem modułu HTTP, który to robi:
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() { }
}
Ten moduł używa następującego filtra do nadpisania zawartości wysłanej do klienta i do przechowywania oryginalnych bajtów (które zawierają wiadomość o wyjątku, ślad stosu i typ 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 niestandardowych błędów dla usług internetowych. Prawdopodobnie chcesz zachować niestandardowe błędy na resztę aplikacji więc web services powinny być umieszczone w podkatalogu. Błędy niestandardowe można wyłączyć w tym katalogu tylko przy użyciu sieci web.config, który nadpisuje ustawienie nadrzędne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-04 11:31:26
Uruchamiasz procedurę składowaną w backendzie. Następnie dla pojedynczej zmiennej zwraca więcej niż 1 wartość. Z tego powodu dochodzi do konfliktu, a ten błąd zostaje wyrzucony.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-14 13:50:59
Wiem, że to nie odpowiada na pytanie per-say, ale poszedłem na własne poszukiwania jakiś czas temu, aby dowiedzieć się o tym i chciałbym się z pustymi rękami. Skończyło się na zawijaniu każdego połączenia usługi internetowej w try / catch, a catch wywołuje nasz rejestrator błędów. Do bani, ale działa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-19 07:48:25
In ASP.Net możliwe jest przechwycenie wszystkich obsługiwanych WYJĄTKÓW za pomocą global Error handler chociaż post na blogu sugeruje, że to nie zadziała, ale możesz eksperymentować z tym podejściem próbując w jakiś sposób zmienić błąd?
Innym pomysłem byłoby spojrzenie na open source elmah (moduły rejestrujące błędy i manipulatory) dla ASP.Net to może pomóc lub ktoś z tej społeczności może mieć pomysł.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-24 10:05:51