поймать всех необработанных исключений в веб ASP.NET API-интерфейс
как поймать все необработанные исключения, которые происходят в ASP.NET веб-Api, чтобы я мог их регистрировать?
до сих пор я пробовал:
- создать и зарегистрировать
ExceptionHandlingAttribute
- реализовать
Application_Error
методGlobal.asax.cs
- подписаться
AppDomain.CurrentDomain.UnhandledException
- подписаться
TaskScheduler.UnobservedTaskException
The ExceptionHandlingAttribute
успешно обрабатывает исключения, которые генерируются в действии контроллера методы и фильтры действий, но другие исключения не обрабатываются, например:
- исключения, когда
IQueryable
возвращенный методом действия не удается выполнить - исключения, создаваемые обработчиком сообщений (т. е.
HttpConfiguration.MessageHandlers
) - исключения, возникающие при создании экземпляра контроллера
в принципе, если исключение приведет к тому, что клиенту будет возвращена Внутренняя ошибка сервера 500, я хочу, чтобы она была зарегистрирована. Реализации Application_Error
хорошо ли эта работа в веб-формах и MVC - что я могу использовать в веб-Api?
5 ответов:
Теперь это возможно с WebAPI 2.1 (см. что нового):
создайте одну или несколько реализаций IExceptionLogger. Например:
public class TraceExceptionLogger : ExceptionLogger { public override void Log(ExceptionLoggerContext context) { Trace.TraceError(context.ExceptionContext.Exception.ToString()); } }
затем зарегистрируйтесь в HttpConfiguration вашего приложения, внутри обратного вызова конфигурации следующим образом:
config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
или напрямую:
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
чтобы ответить на мой собственный вопрос, это не возможно!
обработка всех исключений, которые вызывают внутренние ошибки сервера, похоже, должна иметь базовую возможность Web API, поэтому я отправил запрос в Microsoft для глобальный обработчик ошибок для Web API:
https://aspnetwebstack.codeplex.com/workitem/1001
Если вы согласны, перейдите по этой ссылке и проголосуйте за него!
в то же время, отличная статья ASP.NET обработка исключений Web API показывает несколько различных способов поймать несколько различных категорий ошибок. Это сложнее, чем должно быть, и он не ловит все ошибки сервера interal, но это лучший подход, доступный сегодня.
обновление: глобальная обработка ошибок реализована и доступна в ночных сборках! Он будет выпущен в ASP.NET MVC v5. 1. Вот как это будет работать: https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling
ответ Yuval предназначен для настройки ответов на необработанные исключения, пойманные веб-API, а не для ведения журнала, как указано в связанном страница. Дополнительные сведения см. В разделе когда использовать на странице. Регистратор всегда вызывается, но обработчик вызывается только тогда, когда ответ может быть отправлен. Короче говоря, используйте регистратор для регистрации и обработчика для настройки ответа.
кстати, я использую сборку v5.2. 3 и
ExceptionHandler
класс не имеетHandleCore
метод. Эквивалент, я думаю,Handle
. Однако, просто подклассыExceptionHandler
(как в ответе Юваля) не работает. В моем случае, я должен реализоватьIExceptionHandler
следующим образом.internal class OopsExceptionHandler : IExceptionHandler { private readonly IExceptionHandler _innerHandler; public OopsExceptionHandler (IExceptionHandler innerHandler) { if (innerHandler == null) throw new ArgumentNullException(nameof(innerHandler)); _innerHandler = innerHandler; } public IExceptionHandler InnerHandler { get { return _innerHandler; } } public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) { Handle(context); return Task.FromResult<object>(null); } public void Handle(ExceptionHandlerContext context) { // Create your own custom result here... // In dev, you might want to null out the result // to display the YSOD. // context.Result = null; context.Result = new InternalServerErrorResult(context.Request); } }
обратите внимание, что, в отличие от регистратора, вы регистрируете свой обработчик, заменяя обработчик по умолчанию, а не добавляя.
config.Services.Replace(typeof(IExceptionHandler), new OopsExceptionHandler(config.Services.GetExceptionHandler()));
вы также можете создать глобальный обработчик исключений по реализации
IExceptionHandler
интерфейс (или наследоватьExceptionHandler
базовый класс). Это будет последний вызов в цепочке выполнения, после того, как все зарегистрированныеIExceptionLogger
:IExceptionHandler обрабатывает все необработанные исключения из всех контроллеры. Это последнее в списке. Если возникает исключение, то Сначала будет вызван IExceptionLogger, затем контроллер ExceptionFilters и если все еще необработанный, то IExceptionHandler реализация.
public class OopsExceptionHandler : ExceptionHandler { public override void HandleCore(ExceptionHandlerContext context) { context.Result = new TextPlainErrorResult { Request = context.ExceptionContext.Request, Content = "Oops! Sorry! Something went wrong." }; } private class TextPlainErrorResult : IHttpActionResult { public HttpRequestMessage Request { get; set; } public string Content { get; set; } public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError); response.Content = new StringContent(Content); response.RequestMessage = Request; return Task.FromResult(response); } } }
об этом здесь.
Я думал, что мой новый
global.asax.Application_Error
метод не вызывался последовательно для необработанных исключений в нашем устаревшем коде.затем я нашел несколько блоков try-catch в середине стека вызовов, который вызвал Response.Напишите на текст исключения. Вот и все. Сбросил текст на экран, а затем убил исключение stone dead.