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:
- 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
- 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.
Chociaż nie śledzę tego w moim bieżącym projekcie, prawdopodobnie jest to jedyny sposób, aby niezawodnie wykryć wszystkie te błędy. – Clyde
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