Я использую ASP.MVC 4. У меня сильно типизированный макет, который подключен к базовой модели представления (каждая другая модель представления наследуется от базовой модели представления). Я пытаюсь обрабатывать ошибки, используя стандартный фильтр HandleError. Он из коробки настроен и работает, если макет не сильно типизирован.
Моим примером исключения является следующее:
public class TestController : Controller
{
public ActionResult Index()
{
throw new Exception("oops");
}
}
Когда механизм пытается подключить страницу ошибок к строго типизированному макету, он попадает в проблему, потому что нет модели для него.
Кто-нибудь знает, что такое сценарий для использования строго типизированных макетов с фильтром HandleError? Есть ли возможность установить модель для макета до того, как будет выбрано исключение?
РЕДАКТИРОВАТЬ:
Возможным решением является отключение стандартного механизма обработки ошибок и исключение исключений из метода Application_Error в Global.asax. Пример решения, который вы можете найти здесь: Атрибут ASP.MVC HandleError не работает
В любом случае - если у кого-то есть другое решение, отправьте его.
Единственный способ, о котором я могу думать, - это
Вы можете написать свой собственный атрибут 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());
...
}
Вы можете получить имя контроллера и имя действия, которые воспроизводят ошибку, сделав так:
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