Подтвердить что ты не робот

ASP.NET MVC 4 - Обработка исключений не работает

При возникновении ошибки в моем приложении ASP.NET MVC 4 я хотел бы настроить представление для пользователя в зависимости от типа ошибки. Например, страница не найдена или исключение (с некоторыми удобными для пользователя сведениями об исключении). Я проверил другие примеры того, как это сделать в StackOverflow и других онлайн-источниках, но ни один из ответов не работает для меня.

Базовый атрибут [HandleError], похоже, не работает в VS2012 с приложением MVC 4, ориентированным на .NET 4.5. Вот код, который у меня есть в моем домашнем контроллере:

[HandleError]
public ActionResult Index()
{
    Response.TrySkipIisCustomErrors = true; //doesn't work with or without this
    throw new NullReferenceException("Uh oh, something broke.");
}

Это просто бросает исключение, и я ожидаю, что представление по умолчанию ~/Shared/Error.cshtml будет возвращено из-за атрибута [HandleError], но все, что я получаю, это ошибка внутреннего сервера HTTP 500, указывающая, что страница не отображается. Я проверил свой web.config, и разные конфигурации, похоже, ведут себя странно. В этом разделе в настоящее время содержится:

<customErrors mode="On" />

(Я попытался добавить defaultRedirect и с режимом customErrors = "Off", но это не имело никакого эффекта... не отображается общий доступ к просмотру ошибок или представление CustomError. Если я изменяю customErrors режим выключен, тогда я вижу детали исключения, как ожидалось, поэтому он правильно выбрасывает исключение "Uh oh, something broken".

Я также попытался добавить обработчик OnException в HomeController, и хотя я могу отлаживать и видеть, что событие OnException поднимается, это не имеет никакого значения:

protected override void OnException(ExceptionContext filterContext)
{
    base.OnException(filterContext);
    filterContext.ExceptionHandled = true;
    if (filterContext == null)
    {
        filterContext.Result = View("CustomError");
        return;
    }
    Exception e = filterContext.Exception;
    // TODO: Log the exception here
    ViewData["Exception"] = e; // pass the exception to the view
    filterContext.Result = View("CustomError");
}

Я также попытался изменить [HandleError], чтобы указать представление, но это тоже ничего не делает:

[HandleError(View="CustomError")]

Любая помощь будет высоко оценена. Пожалуйста, дайте мне знать, если вам нужны подробности.

4b9b3361

Ответ 1

Кажется, я помню, что вам приходилось вызывать страницу с IP-адреса не-localhost (обычно на другом компьютере). И он должен быть сервером на базе IIS, а не встроенным сервером разработки (поэтому IIS или IIS Express, но тогда вам нужно настроить IIS Express для внешнего доступа, что является болью).

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

Ответ 2

Я также продолжил бесконечно бесконечное путешествие по чтению ответов SO и сортировку блога, пытаясь заставить страницы пользовательских ошибок работать. Ниже приводится то, что окончательно сработало для меня.

Первым шагом является использование IIS Express для отладки вместо встроенного веб-сервера Cassini, чтобы "гарантировать", что отладочный опыт будет отражать живую среду.

Создайте контроллер для обработки ошибок приложения и добавьте действие для каждой пользовательской ошибки, которую вы будете обрабатывать. Действие должно выполнить любое ведение журнала, установить код состояния и вернуть представление.

public class ErrorsController : Controller
{
    // 404
    [HttpGet]
    public ActionResult NotFound()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    // I also have test actions so that I can verify it working in production.
    [HttpGet]
    public ActionResult Throw404()
    {
        throw new HttpException((int)HttpStatusCode.NotFound, "demo");
    }
}

Настройте раздел customErrors в web.config для перенаправления на ваши пользовательские действия.

  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="Errors/InternalServerError">
      <error statusCode="400" redirect="Errors/BadRequest" />
      <error statusCode="403" redirect="Errors/Forbidden" />
      <error statusCode="404" redirect="Errors/NotFound" />
      <error statusCode="500" redirect="Errors/InternalServerError" />
    </customErrors>

Добавьте раздел httpErrors в system.webServer и установите для параметра errorMode значение Подробно в файле web.config. Почему это работает для меня тайна, но это был ключ.

  <system.webServer>
    <httpErrors errorMode="Detailed" />

Добавьте последний путь к определенным маршрутам, чтобы направить 404s на пользовательскую страницу.

            // catchall for 404s
        routes.MapRoute(
            "Error",
            "{*url}",
            new {controller = "Errors", action = "NotFound"});

Вы также можете создать пользовательский HandleErrorAttribute и зарегистрировать его как глобальный фильтр, чтобы регистрировать 500 ошибок.

Эти шаги работали для меня как в среде разработки (IIS Express), так и в производстве (IIS7). Вам нужно изменить customErrors mode="On", чтобы увидеть эффект в развитии.

Ответ 3

Попробуйте добавить к тегу customErrors следующий атрибут:

defaultRedirect="Error"

Это явно определяет, в каком представлении MVC должен перенаправить пользователя при возникновении ошибки, и по умолчанию в атрибуте не указывается представление. Это, конечно, будет работать только в том случае, если Error.cshtml существует в папке представлений Shared.

Ответ 4

Я столкнулся с подобной проблемой и потерял когда-то попытку выяснить, что происходит. Так что на всякий случай, когда другие сталкиваются с подобной проблемой, вот моя проблема.

Страница ошибки пыталась использовать мою страницу _Layout. Просто убедитесь, что на странице Error.cshtml есть

@{ Layout = null; }