我有一个操作过滤器,负责将一些通用信息放入 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 的新上下文。
有没有什么方法可以让操作过滤器创建的数据可供自定义错误视图使用?
我通过添加另一个过滤器提出了自己的解决方案。
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);
}
}
}
该过滤器需要在 Global.asax.cs 中全局挂接Application_Start()
方法通过调用PreserveViewDataOnExceptionFilter.Register()
.
我在这里所做的是设置一个新的异常过滤器,该过滤器在 HandleErrorAttribute 过滤器运行后最后运行,并复制 ViewData 集合的内容,该内容可供控制器使用,该控制器将异常抛出到由 HandleErrorAttribute 过滤器创建的结果中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)