Глобально регистрируйте исключения из служб ASP.NET [ScriptService] - PullRequest
13 голосов
/ 24 января 2009

Я использую тег [System.Web.Script.Services.ScriptService] для использования веб-сервисов, вызываемых из клиентского JavaScript. Что мне нужно, так это способ глобальной регистрации любых необработанных исключений в этих методах. На стороне клиента я получаю сообщение об ошибке и могу оттуда продолжить, но мне нужен серверный перехват для регистрации исключения.

Парень по этому адресу: http://ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx

предполагает, что это невозможно сделать.

Это точно? Должен ли я серьезно обратиться к каждому веб-методу во всей системе и попробовать / поймать метод в целом.

Ответы [ 4 ]

15 голосов
/ 15 февраля 2009

Вы можете использовать модуль HTTP для захвата сообщения об исключении, трассировки стека и типа исключения, создаваемого методом веб-службы.

Сначала немного фона ...

  • Если метод веб-службы выдает исключение, ответ HTTP имеет код состояния 500.

  • Если пользовательские ошибки отключены, то в Интернете сервис вернет исключение трассировка сообщения и стека клиенту как JSON. Например:
    {"Message":"Exception message","StackTrace":" at WebApplication.HelloService.HelloWorld() in C:\Projects\Stackoverflow Examples\WebApplication\WebApplication\HelloService.asmx.cs:line 22","ExceptionType":"System.ApplicationException"}

  • Когда пользовательские ошибки включены, то веб-сервис возвращает сообщение по умолчанию клиенту и удаляет стек тип трассировки и исключения:
    {"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}

Итак, нам нужно отключить пользовательские ошибки для веб-службы и подключить модуль HTTP, который:

  1. Проверяет, относится ли запрос к методу веб-службы
  2. Проверяет, было ли создано исключение, то есть возвращается код состояния 500
  3. Если 1) и 2) имеют значение true, тогда получите исходный 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.config, который переопределяет родительский параметр.

3 голосов
/ 14 декабря 2012

Вы запускаете хранимую процедуру в бэкэнде. Затем для одной переменной возвращается более 1 значения. Из-за этого возникает конфликт, и выдается эта ошибка.

1 голос
/ 19 февраля 2009

Я знаю, что это не отвечает на вопрос, скажем так, но я некоторое время назад отправлялся в свой собственный квест, чтобы выяснить это, и поднялся бы с пустыми руками. Закончилось завершение каждого вызова веб-службы в try / catch, и catch вызывает наш журнал ошибок. Отстой, но это работает.

0 голосов
/ 24 января 2009

В ASP.Net можно перехватывать все обработанные исключения при запуске, используя глобальный обработчик ошибок , хотя в блоге предполагается, что это не будет работать, но вы можете поэкспериментировать с этим подходом, пытаясь сбросить ошибку в некоторых способ

Другой идеей было бы взглянуть на открытый исходный код elmah (Модули и обработчики ошибок) для ASP.Net, который может помочь, или кто-то в этом сообществе может иметь идею.

...