2011-12-15 2 views
5

Я создал приложение ASP.NET MVC 3, используя httpErrors, чтобы обрабатывать отображение сообщений об ошибках и т.п. пользователю. Этот код работает нормально и дублируется ниже.Передача исключения на пользовательскую страницу ошибки с использованием IIS7 httpErrors

<httpErrors existingResponse="Replace" defaultResponseMode="ExecuteURL" errorMode="Custom"> 
    <clear/> 
    <error statusCode="403" path="/Error/Forbidden" responseMode="ExecuteURL"/> 
    <error statusCode="404" subStatusCode="-1" path="/Error/NotFound" responseMode="ExecuteURL"/> 
    <error statusCode="500" subStatusCode="-1" path="/Error/ServerError" responseMode="ExecuteURL"/> 
</httpErrors> 

Когда исключение в контроллере происходит, BaseController.OnException срабатывает (BaseController класс моего собственного творчества). То, что я хочу сделать в этой функции, заключается в сохранении исключения, так что мое действие ServerError может посмотреть на его тип и сообщение, чтобы определить, что показывать пользователю. Весь метод копируется ниже.

protected override void OnException(ExceptionContext filterContext) 
{ 
    // doesn't work 
    this.TempData["exception"] = filterContext.Exception; 

    // doesn't work 
    this.Session["exception"] = filterContext.Exception; 

    // temporary hack 
    ErrorController.RequestExceptions[this.Request.UserHostAddress] = filterContext.Exception; 
    base.OnException(filterContext); 
} 

Когда поступает запрос на ErrorController экземпляр (ErrorController находится в другом пространстве имен, но я не думаю, что это уместно), по какой-то причине Server.GetLastError() возвращает NULL, TempData пуст, сессия пуста, и Session.IsNewSession правда. Я попытался решить проблему, установив в App Store какой-то идентификатор запроса, но это, похоже, не существует, и сейчас самое лучшее решение, которое у меня есть, - это очень хакерский «хранить его, запрашивая IP-адрес, а затем удалять это как только ErrorController поднял его ».

Это (удивительно) работает, но должно быть более безопасное и масштабируемое решение. Я не уверен, почему TempData очищается или почему сеанс перезагружен - это из-за ошибки, или это считается двумя отдельными запросами? Независимо от того, есть ли временное решение для получения желаемого поведения?

P.S. Я предпочел бы, по возможности, использовать запись httpErrors в файле web.config, а не в коде Application_Error: это похоже на более чистое, более декларативное решение.

P.P.S. Я нашел статью о проблемах с объектом Session во время перенаправления (link), но он говорит, что проблема исправлена. Большинство других вещей, с которыми я столкнулся, касались более старой системы customErrors, но я буду продолжать искать.

+0

Все новости о том, почему сессия очищается. У меня точно такая же проблема. Танки –

ответ

2

MVC имеет встроенную поддержку для обработки исключений и отображения пользовательского вида. По умолчанию MVC добавляет HandleErrorAttribute к методу RegisterGlobalFilters в файле Global.asax.cs.

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
    } 

Вам нужно добавить представление именованного Error в папку с Shared просмотра. Вид будет иметь модель типа HandleErrorInfo которая как свойство с именем Exception, чтобы получить выброшенное исключение

@model System.Web.Mvc.HandleErrorInfo 

@Model.Exception.Message 
+0

Так что «httpErrors» там путают, или это значит служить какой-то другой цели, которую я не понимаю? – ehdv

+0

@ehdv MVC выполняется поверх времени выполнения Asp.Net. Если MVC выбрасывает исключение (и вы не обрабатываете его в MVC), он будет обрабатываться во время выполнения Asp.Net с помощью соответствующего обработчика 'httpErrors'. – Eranga