Задний план
Я разрабатываю сервисный уровень API для клиента, и меня попросили перехватывать и регистрировать все ошибки в глобальном масштабе.
Таким образом, хотя что-то вроде неизвестной конечной точки (или действия) легко обрабатывается с помощью ELMAH или путем добавления чего-то вроде этого в Global.asax
:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
//do more stuff
}
, , Необработанные ошибки, не связанные с маршрутизацией, не регистрируются. Например:
public class ReportController : ApiController
{
public int test()
{
var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
return foo;
}
}
Я также попытался установить [HandleError]
атрибут глобально, зарегистрировав этот фильтр:
filters.Add(new HandleErrorAttribute());
Но это также не регистрирует все ошибки.
Проблема / Вопрос
Как перехватить ошибки, подобные той, которая генерируется при вызове /test
выше, чтобы я мог их регистрировать? Кажется, что этот ответ должен быть очевидным, но я перепробовал все, что только могу придумать.
В идеале я хочу добавить в журнал ошибок некоторые вещи, такие как IP-адрес запрашивающего пользователя, дату, время и т. Д. Я также хочу, чтобы сотрудники службы поддержки могли по электронной почте автоматически при обнаружении ошибки. Все это я могу сделать, если только я могу перехватить эти ошибки, когда они случаются!
ПОСТАНОВИЛИ!
Благодаря Дарину Димитрову, чей ответ я принял, я понял это. WebAPI не обрабатывает ошибки так же, как обычный контроллер MVC.
Вот что сработало:
1) Добавьте пользовательский фильтр в ваше пространство имен:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BusinessException)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
ReasonPhrase = "Exception"
});
}
//Log Critical errors
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred, please try again or contact the administrator."),
ReasonPhrase = "Critical Exception"
});
}
}
2) Теперь зарегистрируйте фильтр глобально в классе WebApiConfig :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
config.Filters.Add(new ExceptionHandlingAttribute());
}
}
ИЛИ вы можете пропустить регистрацию и просто украсить отдельный контроллер с [ExceptionHandling]
атрибутом.
источник
Ответы:
Если ваш веб-API размещен внутри приложения ASP.NET,Application_Error
событие будет вызываться для всех необработанных исключений в вашем коде, в том числе в тестовом действии, которое вы показали. Поэтому все, что вам нужно сделать, это обработать это исключение внутри события Application_Error. В показанном вами примере кода вы обрабатываете только исключение типа,HttpException
что, очевидно, не относится кConvert.ToInt32("a")
коду. Поэтому убедитесь, что вы регистрируете и обрабатываете все исключения там:Обработка исключений в Web API может выполняться на разных уровнях. Вот
detailed article
объяснение различных возможностей:атрибут фильтра пользовательских исключений, который может быть зарегистрирован как глобальный фильтр исключений
пользователь, выполняющий пользовательские действия
источник
Application_Error
событие, это означает, что какой-то другой код потребляет его раньше. Например, у вас могут быть некоторые пользовательские атрибуты HandleErrorAttributes, пользовательские модули, ... Есть десятки других мест, где исключения могут быть перехвачены и обработаны. Но лучшее место для этого - событие Application_Error, потому что на этом все необработанные исключения будут заканчиваться./test
пример не получил успеха. Я поставил точку останова на первой строке (Exception unhandledException = . . .
), но не могу достичь этой точки останова в/test
сценарии. Однако, если я введу фиктивный URL, точка останова будет достигнута.Application_Error
Событие не является правильным местом для обработки исключений для Web API , поскольку он не будет срабатывать во всех случаях. Я нашел очень подробную статью, объясняющую различные возможности для достижения этой цели: weblogs.asp.net/fredriknormen/archive/2012/06/11/…Как дополнение к предыдущим ответам.
Вчера был официально выпущен ASP.NET Web API 2.1 .
Это дает еще одну возможность обрабатывать исключения во всем мире.
Детали приведены в образце .
Вкратце, вы добавляете глобальные регистраторы исключений и / или глобальный обработчик исключений (только один).
Вы добавляете их в конфигурацию:
И их реализация:
источник
Зачем отбрасывать и т. Д.? Это работает, и сервис вернет статус 500 и т. Д.
источник
Вы думали о том, чтобы сделать что-то вроде фильтра действия ошибки дескриптора, как
Вы также можете создать собственную версию
[HandleError]
с которой вы можете написать информацию об ошибке и все другие детали для входаисточник
Оберните все это в попытку / поймайте и зарегистрируйте необработанное исключение, а затем передайте его. Если нет лучшего встроенного способа сделать это.
Вот ссылка Catch All (обработано или необработано) Исключения
(редактировать: о, API)
источник