如何将ViewData传递给HandleError视图?
问题描述:
在我的Site.Master文件中,我有3个简单的ViewData参数(我的整个解决方案中只有3个)。这些ViewData值对于我的应用程序中的每个页面都很重要。由于在我的Site.Master中使用了这些值,我创建了一个抽象的SiteController类,它覆盖了OnActionExecuting方法,为我的解决方案中每个控制器上的每个Action方法填充这些值。如何将ViewData传递给HandleError视图?
[HandleError(ExceptionType=typeof(MyException), View="MyErrorView")]
public abstract class SiteController : Controller
{
protected override void OnActionExecuting(...)
{
ViewData["Theme"] = "BlueTheme";
ViewData["SiteName"] = "Company XYZ Web Portal";
ViewData["HeaderMessage"] = "Some message...";
base.OnActionExecuting(filterContext);
}
}
我正在面临的问题是,这些值不被传递给MyErrorView(并且最终的Site.Master)当HandleErrorAttribute从SiteController类级别属性在踢。下面是一个简单的场景来展现我的问题:
public class TestingController : SiteController
{
public ActionResult DoSomething()
{
throw new MyException("pwnd!");
}
}
我试图通过覆盖在我的SiteController的onException的()方法,以及填充ViewData的参数,但无济于事。 :(
什么是通过在这种情况下,ViewData的参数,我的Site.Master的最佳方式?
答
这是因为HandleErrorAttribute改变的ViewData传递时发生错误的观点,它传递的一个实例。HandleErrorInfo类有关的异常,控制器和动作信息
你可以做的是替换为一个低于实施该属性:
using System;
using System.Web;
using System.Web.Mvc;
public class MyHandleErrorAttribute : HandleErrorAttribute {
public override void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)
{
Exception innerException = filterContext.Exception;
if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
{
string controllerName = (string) filterContext.RouteData.Values["controller"];
string actionName = (string) filterContext.RouteData.Values["action"];
// Preserve old ViewData here
var viewData = new ViewDataDictionary<HandleErrorInfo>(filterContext.Controller.ViewData);
// Set the Exception information model here
viewData.Model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
filterContext.Result = new ViewResult { ViewName = this.View, MasterName = this.Master, ViewData = viewData, TempData = filterContext.Controller.TempData };
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}
}
答
如果你只需要通过ViewBag传递的东西也可以是唐è这样的:(这恰好是在BaseController我所有的控制器继承)
protected override void OnException(ExceptionContext filterContext)
{
try
{
var v = filterContext.Result as ViewResult;
v.ViewBag.DataToPassToError = "Hello World!";
}
catch { /* no-op */ }
base.OnException(filterContext);
}
在这里看到:How can I use data placed into a ViewBag by a filter in my Error.cshtml view?
哇,这是一个很多比我想象的要复杂得多。 :)我已经通过它来了解它,它是完全有意义的,你在做什么,为什么你这样做。感谢您的回答! – Luc 2009-12-01 19:29:31
这实际上并不工作... – fearofawhackplanet 2012-01-17 12:47:15
“不起作用”并不特别有用。我为我和其他人做了。你应该检查你使用的MVC版本,因为我相信很多改变了。 – 2012-01-17 19:47:14