如何将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; 
      } 
     } 
    } 
} 
+0

哇,这是一个很多比我想象的要复杂得多。 :)我已经通过它来了解它,它是完全有意义的,你在做什么,为什么你这样做。感谢您的回答! – Luc 2009-12-01 19:29:31

+1

这实际上并不工作... – fearofawhackplanet 2012-01-17 12:47:15

+0

“不起作用”并不特别有用。我为我和其他人做了。你应该检查你使用的MVC版本,因为我相信很多改变了。 – 2012-01-17 19:47:14

如果你只需要通过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?