Asp.net mvc 如何在我的Error.cshtml视图中使用过滤器放入ViewBag的数据?
我有一个动作过滤器,负责将一些公共信息放入ViewBag中,供shared _Layout.cshtml文件中的所有视图使用Asp.net mvc 如何在我的Error.cshtml视图中使用过滤器放入ViewBag的数据?,asp.net-mvc,asp.net-mvc-3,action-filter,viewbag,Asp.net Mvc,Asp.net Mvc 3,Action Filter,Viewbag,我有一个动作过滤器,负责将一些公共信息放入ViewBag中,供shared _Layout.cshtml文件中的所有视图使用 public class ProductInfoFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { // build product info
public class ProductInfoFilterAttribute : ActionFilterAttribute
{
public override void
OnActionExecuting(ActionExecutingContext filterContext)
{
// build product info
// ... (code omitted)
dynamic viewBag = filterContext.Controller.ViewBag;
viewBag.ProductInfo = info;
}
}
在shared _Layout.cshtml文件中,我使用已放入ViewBag的信息
...
@ViewBag.ProductInfo.Name
...
如果在处理控制器操作时发生异常,则标准HandleErrorAttribute应显示my shared Error.cshtml视图,这在我引入上述操作筛选器并开始使用_Layout.cshtml中ViewBag中的新值之前就已经起作用了。现在我得到的是标准的ASP.Net运行时错误页面,而不是我的自定义error.cshtml视图
我已经追踪到这样一个事实:在呈现错误视图时,在_Layout.cshtml中使用ViewBag.ProductInfo.Name时会抛出RuntimeBinderException(“无法对空引用执行运行时绑定”)
看起来,即使我的操作筛选器在引发原始异常之前已成功设置ViewBag中的值,但在呈现my Error.cshtml视图时,仍会使用带有空ViewBag的新上下文
有没有办法让动作过滤器创建的数据可用于自定义错误视图?通过添加另一个过滤器,我想出了自己的解决方案
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);
}
}
}
公共类PreserveViewDataOneExceptionFilter:IEExceptionFilter
{
公共空间
OneException(例外上下文筛选器上下文)
{
//将视图数据内容从控制器复制到结果视图
ViewResult ViewResult=filterContext.Result作为ViewResult;
如果(viewResult!=null)
{
foreach(filterContext.Controller.ViewData中的var值) { 如果(!viewResult.ViewData.ContainsKey(value.Key)) { viewResult.ViewData[value.Key]=value.value; } } } } 公共静态空间 寄存器() { 添加(新的FilterProvider()); } 私有类筛选器提供程序:IFilterProvider { 公共数字 GetFilters(ControllerContext ControllerContext、ActionDescriptor ActionDescriptor) { //将筛选器作为所有控制器/操作的“第一个”附加;注意:异常筛选器按相反顺序运行 //所以这确实会导致过滤器成为最后一个执行的过滤器 返回新筛选器(新的PreserveViewDataOneExceptionFilter(),FilterScope.First,null); } } } 需要通过调用
preserveViewDataOneExceptionFilter.Register()
将此筛选器全局挂接到Global.asax.cs应用程序\u Start()
方法中
我在这里所做的是设置一个新的异常过滤器,该过滤器在HandleErrorAttribute过滤器运行之后最后运行,并将引发异常的控制器可用的ViewData集合的内容复制到HandleErrorAttribute筛选器创建的结果中。这对ViewData非常有效,我喜欢这段代码,但是你有与ViewBag等效的吗?filterContext.Controller.ViewData包含我所能看到的模型和ViewBag,因此可以将其全部传递,或者仅传递所需的位