GBe*_*gen 18 asp.net-mvc action-filter viewbag asp.net-mvc-3
我有一个动作过滤器,负责将一些常见信息放入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;
}
}
Run Code Online (Sandbox Code Playgroud)
在共享的_Layout.cshtml文件中,我使用已放入ViewBag的信息.
...
@ViewBag.ProductInfo.Name
...
Run Code Online (Sandbox Code Playgroud)
如果处理控制器动作时发生异常,标准HandleErrorAttribute应显示我的共享Error.cshtml视图,并且这个工作之前予介绍上面的动作过滤器,并使用在_Layout.cshtml从ViewBag新的值开始.现在我得到的是标准的ASP.Net运行时错误页面,而不是我的自定义Error.cshtml视图.
我已经跟踪下来的事实,在渲染的错误观点,一个RuntimeBinderException("不能执行运行时的空引用结合")被抛出在_Layout.cshtml使用ViewBag.ProductInfo.Name的.
即使我的动作过滤器在抛出原始异常之前已在ViewBag中成功设置了值,但在渲染我的Error.cshtml视图时,仍会使用带有空ViewBag的新上下文.
有没有办法让动作过滤器创建的数据可用于自定义错误视图?
GBe*_*gen 12
我通过添加另一个过滤器来提出自己的解决方案.
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
需要Application_Start()通过调用将此过滤器全局挂接到Global.asax.cs 方法中PreserveViewDataOnExceptionFilter.Register().
我在这里做的是设置一个新的异常过滤器,它在HandleErrorAttribute过滤器运行之后运行到最后,并复制可用于控件的ViewData集合的内容,该控件将异常抛出到HandleErrorAttribute过滤器创建的结果中.
| 归档时间: |
|
| 查看次数: |
11434 次 |
| 最近记录: |