简体   繁体   English

ASP.MVC中的HandleError和强类型布局

[英]HandleError and strongly typed layout in ASP.MVC

I'm using ASP.MVC 4. I have a strongly typed layout which is connected to a base view model (every other view model is inheriting from the base view model). 我正在使用ASP.MVC4。我有一个强类型的布局,该布局已连接到基本视图模型(每个其他视图模型都从基本视图模型继承)。 I'm trying to handle errors using a standard HandleError filter. 我正在尝试使用标准的HandleError过滤器来处理错误。 It's out of box configured and works if layout isn't strongly typed. 它是开箱即用的配置,如果布局不是强类型的,则可以使用。

My example exception is following: 我的示例异常如下:

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

When the mechanism tries to plug Error page into strongly typed layout it gets in trouble because there's no model for it. 当该机制尝试将“错误”页面插入强类型布局时,就会遇到麻烦,因为它没有模型。

Does anyone know what is a scenario for using strongly typed layouts with the HandleError filter? 有谁知道在HandleError过滤器中使用强类型布局的情况? Is there any possibility to set model for the layout before the exception is thrown? 是否可以在引发异常之前为布局设置模型?

EDIT: 编辑:

Possible solution is turning off standard error handling mechanism and catching exceptions in the Application_Error method in the Global.asax. 可能的解决方案是关闭标准错误处理机制,并在Global.asax的Application_Error方法中捕获异常。 Example solution you can find here: ASP.MVC HandleError attribute doesn't work 您可以在此处找到示例解决方案: ASP.MVC HandleError属性不起作用

Anyway - if someone have another solution, please post it. 无论如何-如果有人有其他解决方案,请发布。

You could write your own HandleError attribute and register it on FilterConfig instead of the default one. 您可以编写自己的HandleError属性,然后将其注册到FilterConfig而不是默认属性。 Your custom one will extend the default attribute, overriding the result so the model instance passed into the view is of the required type: 您的自定义变量将扩展默认属性,并覆盖结果,因此传递到视图中的模型实例为必需的类型:

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;
    }
}

Then register globally this filter instead of the default HandleErrorAttribute : 然后在全局范围内注册此过滤器,而不是默认的HandleErrorAttribute

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

Only way I can think of is 我唯一能想到的是

  • a) In Global.asax.cs, handle Application_Error (or Application_OnError, the signature escapes me now) and redirect to a strongly typed view a)在Global.asax.cs中,处理Application_Error(或Application_OnError,签名现在转义了我)并重定向到强类型视图
  • b) Edit web.config customErrors section to point to your strongly typed view. b)编辑web.config customErrors部分以指向您的强类型视图。 However, doing b) can be flakey as other have found eg benfoster.io/blog/aspnet-mvc-custom-error-pages 但是,执行b)可以像其他方法一样容易,例如benfoster.io/blog/aspnet-mvc-custom-error-pages

You can get the controller name and the action name that reproduce the error by doing so: 您可以通过执行以下操作来获取重现该错误的控制器名称和操作名称:

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;
    }
}

in the "CustomError.cshtml" view you can do this: 在“ CustomError.cshtml”视图中,您可以执行以下操作:
@model HandleErrorInfo @model HandleErrorInfo
Hey this is a custom error!!! 嘿,这是一个自定义错误!!!
Controller name: @Model.ControllerName 控制器名称:@ Model.ControllerName
action name: @Model.ActionName 动作名称:@ Model.ActionName
Exception message: @Model.Exception.Message 异常消息:@ Model.Exception.Message

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM