Как использовать 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.