我有一个操作过滤器,负责将一些常见信息放到ViewBag中,以供共享_Layout.cshtml文件中的所有视图使用。
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中的信息。
...
@ViewBag.ProductInfo.Name
...
如果在处理控制器操作时发生异常,标准HandleErrorAttribute应该显示我的共享Error.cshtml视图,在我引入上面的操作过滤器并开始在_Layout.cshtml中使用来自ViewBag的新值之前,这是有效的。现在,我得到的是标准的ASP.Net运行时错误页面,而不是我的自定义Error.cshtml视图。
我已经追踪到这样一个事实:在呈现错误视图时,在_Layout.cshtml中使用ViewBag.ProductInfo.Name时会抛出RuntimeBinderException (“无法在空引用上执行运行时绑定”)。
即使我的操作过滤器在抛出原始异常之前已经成功地设置了ViewBag中的值,在呈现我的Error.cshtml视图时,仍然使用了一个具有空ViewBag的新上下文。
有没有办法让操作筛选器创建的数据可用于自定义错误视图?
发布于 2011-07-07 07:30:16
通过添加另一个过滤器,我提出了自己的解决方案。
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筛选器创建的结果中的控制器。
https://stackoverflow.com/questions/6602638
复制相似问题