ELMAH не работает, так как использует глобальный обработчик ошибок, который подавляет атрибут [ScriptServer].

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

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

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

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

Ответы на вопрос(4)

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

Решение Вопроса

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

Сначала немного предыстории ...

Если метод веб-службы выдает исключение, ответ 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, который:

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

 Clyde19 февр. 2009 г., 18:45
Несмотря на то, что я не выполняю это в моем текущем проекте, это, вероятно, единственный способ надежно уловить все эти ошибки.
 maxisam06 сент. 2013 г., 23:15
Я попробовал это, но каким-то образом мой context.Response.Filter.length вызвал исключение типа «System.NotSupportedException». Это просто не работает. Я думаю, что это очень близко, мой вывод в точности, как вы сказали. и я получил 500 кодов статуса.

глобальный обработчик ошибок хотя сообщение в блоге предполагает, что это не будет работать, но вы могли бы поэкспериментировать с этим подходом, пытаясь каким-то образом устранить ошибку?

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

 Clyde24 янв. 2009 г., 16:36
Тем не менее, ссылка на Elmah интересна ... Я обязательно проверю это
 Clyde24 янв. 2009 г., 16:35
Да, я не уверен, что вы действительно поняли проблему. Исключениеявляется пойманный код службы сценариев ASP.NET - пойман прежде, чем у меня есть шанс поймать его. Таким образом, глобальный обработчик ошибок не работает. Фреймворк отправляет сообщение об ошибке на стороне клиента, чтобы я мог отобразить сообщение, но серверный хук отсутствует
 WiseGuyEh23 янв. 2013 г., 10:20
ELMAH не работает, так как использует глобальный обработчик ошибок, который подавляет атрибут [ScriptServer].
 Dave Ward17 февр. 2009 г., 04:33
Я бы второй ELMAH. Я использую это именно для этой цели сам.

возвращается более 1 значения. Из-за этого возникает конфликт, и эта ошибка выдается.

Ваш ответ на вопрос