HandleError и строго типизированный макет в ASP.MVC

1

Я использую ASP.MVC 4. У меня сильно типизированный макет, который подключен к базовой модели представления (каждая другая модель представления наследуется от базовой модели представления). Я пытаюсь обрабатывать ошибки, используя стандартный фильтр HandleError. Он из коробки настроен и работает, если макет не сильно типизирован.

Моим примером исключения является следующее:

public class TestController : Controller
{
    public ActionResult Index()
    {
        throw new Exception("oops");
    }
}

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

Кто-нибудь знает, что такое сценарий для использования строго типизированных макетов с фильтром HandleError? Есть ли возможность установить модель для макета до того, как будет выбрано исключение?

РЕДАКТИРОВАТЬ:

Возможным решением является отключение стандартного механизма обработки ошибок и исключение исключений из метода Application_Error в Global.asax. Пример решения, который вы можете найти здесь: Атрибут ASP.MVC HandleError не работает

В любом случае - если у кого-то есть другое решение, отправьте его.

Теги:
asp.net-mvc
asp.net-mvc-4

3 ответа

1
Лучший ответ

Единственный способ, о котором я могу думать, - это

  • a) В Global.asax.cs обрабатывать Application_Error (или Application_OnError, подпись меня ускоряет) и перенаправить на строго типизированное представление
  • b) Отредактируйте раздел web.config customErrors, чтобы указать на строго типизированное представление. Однако выполнение b) может быть ошибочным, поскольку другие обнаружили, например, benfoster.io/blog/aspnet-mvc-custom-error-pages
4

Вы можете написать свой собственный атрибут HandleError и зарегистрировать его на FilterConfig вместо стандартного. Ваш пользовательский расширяет атрибут по умолчанию, переопределяя результат, поэтому экземпляр модели, переданный в представление, имеет требуемый тип:

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        //When already handled, do nothing
        if (context.ExceptionHandled)
            return;

        //Run the base functionality
        base.OnException(context);

        //If the base functionality didnt handle the exception, then exit (as the exception is not of the type this filter should handle)
        if (!context.ExceptionHandled) return;

        //Set a view as the result           
        context.Result = GetViewResult(context);            
    }

    private ViewResult GetViewResult(ExceptionContext context)
    {
        //The model of the error view (YourModelType) will inherit from the base view model required in the layout
        YourModelType model = new YourModelType(context.Exception, ...);
        var result = new ViewResult
        {
            ViewName = View,
            ViewData = new ViewDataDictionary<YourModelType>(model),
            TempData = context.Controller.TempData
        };
        return result;
    }
}

Затем зарегистрируйте глобально этот фильтр вместо стандартного HandleErrorAttribute:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new CustomHandleErrorAttribute());
    ...
}
  • 0
    Ваше решение выглядит красиво. Я использовал метод Application_Error, но я проверю ваш код в свободное время.
  • 0
    +1 Мне тоже нравится этот подход.
0

Вы можете получить имя контроллера и имя действия, которые воспроизводят ошибку, сделав так:

public class CustomErrorException: HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.Result = new ViewResult {
            ViewName = "CustomError",
            ViewData = new ViewDataDictionary<HandleErrorInfo> { 
                Model = new HandleErrorInfo(
                    exception: filterContext.Exception,
                    controllerName: filterContext.RequestContext.RouteData.Values["controller"].ToString(),
                    actionName: filterContext.RequestContext.RouteData.Values["action"].ToString()
                ) 
            }
        };

        //You can log your errors here.
        filterContext.ExceptionHandled = true;
    }
}

в представлении "CustomError.cshtml" вы можете сделать это:
@model HandleErrorInfo
Эй, это обычная ошибка !!!
Имя контроллера: @Model.ControllerName
название действия: @Model.ActionName
Сообщение об исключении: @Model.Exception.Message

Ещё вопросы

Сообщество Overcoder
Наверх
Меню