首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用通过Error.cshtml视图中的过滤器放入ViewBag中的数据?

如何使用通过Error.cshtml视图中的过滤器放入ViewBag中的数据?
EN

Stack Overflow用户
提问于 2011-07-07 04:37:36
回答 1查看 12.1K关注 0票数 18

我有一个操作过滤器,负责将一些常见信息放到ViewBag中,以供共享_Layout.cshtml文件中的所有视图使用。

代码语言:javascript
复制
public class ProductInfoFilterAttribute : ActionFilterAttribute
{
    public override void
    OnActionExecuting(ActionExecutingContext filterContext)
    {
        //  build product info
        //  ... (code omitted)

        dynamic viewBag = filterContext.Controller.ViewBag;
        viewBag.ProductInfo = info;
    }
}

在共享的_Layout.cshtml文件中,我使用了放入ViewBag中的信息。

代码语言:javascript
复制
...
@ViewBag.ProductInfo.Name
...

如果在处理控制器操作时发生异常,标准HandleErrorAttribute应该显示我的共享Error.cshtml视图,在我引入上面的操作过滤器并开始在_Layout.cshtml中使用来自ViewBag的新值之前,这是有效的。现在,我得到的是标准的ASP.Net运行时错误页面,而不是我的自定义Error.cshtml视图。

我已经追踪到这样一个事实:在呈现错误视图时,在_Layout.cshtml中使用ViewBag.ProductInfo.Name时会抛出RuntimeBinderException (“无法在空引用上执行运行时绑定”)。

即使我的操作过滤器在抛出原始异常之前已经成功地设置了ViewBag中的值,在呈现我的Error.cshtml视图时,仍然使用了一个具有空ViewBag的新上下文。

有没有办法让操作筛选器创建的数据可用于自定义错误视图?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-07 07:30:16

通过添加另一个过滤器,我提出了自己的解决方案。

代码语言:javascript
复制
public class PreserveViewDataOnExceptionFilter : IExceptionFilter
{
    public void
    OnException(ExceptionContext filterContext)
    {
        //  copy view data contents from controller to result view
        ViewResult viewResult = filterContext.Result as ViewResult;
        if ( viewResult != null )
        {
            foreach ( var value in filterContext.Controller.ViewData )
            {
                if ( ! viewResult.ViewData.ContainsKey(value.Key) )
                {
                    viewResult.ViewData[value.Key] = value.Value;
                }
            }
        }
    }

    public static void
    Register()
    {
        FilterProviders.Providers.Add(new FilterProvider());
    }

    private class FilterProvider : IFilterProvider
    {
        public IEnumerable<Filter>
        GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            //  attach filter as "first" for all controllers / actions; note: exception filters run in reverse order
            //  so this really causes the filter to be the last filter to execute
            yield return new Filter(new PreserveViewDataOnExceptionFilter(), FilterScope.First, null);
        }
    }
}

此筛选器需要通过调用PreserveViewDataOnExceptionFilter.Register()在Global.asax.cs Application_Start()方法中全局挂钩。

我在这里所做的是设置一个新的异常筛选器,它在HandleErrorAttribute筛选器运行之后最后运行,并将ViewData集合的内容复制到将异常抛出到HandleErrorAttribute筛选器创建的结果中的控制器。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6602638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档