Как использовать Application_Error в ASP.NET MVC?
Я хочу использовать Application_Error с моим проектом MVC, но я не могу заставить его работать. Я добавляю следующее в свой файл Global.asax:
protected void Application_Error(object sender, EventArgs e)
{
Exception objErr = Server.GetLastError().GetBaseException();
Session["Test"] = "Message:" + objErr.Message.ToString();
}
(Сессия предназначена только для тестов. Я собираюсь использовать базу данных для регистрации ошибки, если я получу это для работы.)
Затем я пытаюсь выбросить исключение из моего HomeController и моего Home/Index View, но он вызывает только Debug.
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
throw (new Exception());
return View();
}
В моем файле Webconfig я устанавливаю страницу defaulterror, но он не перенаправляется на представление:
<customErrors defaultRedirect="Home/Error">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
Ответы
Ответ 1
Итак, во-первых, помните, что глобальная обработка ошибок должна быть последней инстанцией, а классы контроллеров имеют определенный метод ошибок для ошибок;
protected virtual bool OnError(string actionName,
System.Reflection.MethodInfo methodInfo, Exception exception)
В этом случае вы можете перенаправить на стандартное представление общей ошибки;
protected override bool OnError(string actionName,
System.Reflection.MethodInfo methodInfo, Exception exception)
{
RenderView("Error", exception);
return false;
}
Проблема, с которой вы столкнулись в глобальной ошибке приложения, состоит в том, что у нее нет концепции представлений или контроллеров, поэтому, если вы хотите перенаправить туда, вы должны использовать известный URL
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
System.Diagnostics.Debug.WriteLine(exception);
Response.Redirect("/Home/Error");
}
но вам не нужно это делать. Если вы установили страницу ошибки по умолчанию в web.config, вам не понадобится перенаправление
<customErrors defaultRedirect="Home/Error" />
Однако, если вы не добавили представление об ошибке на свой домашний контроллер, которого не существует, добавьте следующее в домашний контроллер
public ActionResult Error()
{
return View();
}
Затем (если вы разумны) вы поместили код обработки ошибок в метод Error(), как тот, где все необработанные ошибки закончились.
public ActionResult Error()
{
Exception exception = Server.GetLastError();
System.Diagnostics.Debug.WriteLine(exception);
return View();
}
И, наконец, помните, что по умолчанию вы не видите пользовательские ошибки, если вы подключаетесь к localhost! Поэтому вам нужно изменить это поведение
<customErrors mode="On" defaultRedirect="/Home/Error" />
Ответ 2
- У вас есть Сессия, созданная в первую очередь? Если ошибка вызвана из
IHttpHandler
, не отмеченной IRequiresSessionState
, тогда доступ к Session
завершится с ошибкой.
- Что вы делаете с
Session["Test"]
? Вы уверены, что ваш код на самом деле не работает? Вы можете попробовать File.Open и просто вывести некоторый текст (скажем, текущее время) на C:\my-log.txt
, что немного более вероятно, чем с помощью Session
.
-
GetBaseException
не полезен в этом случае (и вообще для ведения журнала), насколько я могу судить.
-
Message
имеет тип string
- вызов .ToString()
не требуется. В общем, я настоятельно рекомендую избегать ToString()
там, где это возможно - если вы используете его, потому что вы не уверены в типе объекта, это должен быть красный флаг; выполнение конца системы типа может скрыть тонкие ошибки (например, DBNull.Value.ToString() == ""
). Для графического интерфейса встроенные типы обеспечивают перегрузку .ToString(IFormatProvider)
, чувствительную к культуре, и исключают проблемы с переносимостью. Поскольку эта перегрузка также отсутствует на object
, это также является защитой, чтобы избежать очень слабо типизированных вызовов .ToString
.