如何将 ViewData 传递到 HandleError 视图?

发布于 2024-08-12 12:06:43 字数 1026 浏览 7 评论 0原文

在我的 Site.Master 文件中,我有 3 个简单的 ViewData 参数(整个解决方案中仅有的 3 个参数)。这些 ViewData 值对于我的应用程序中的每个页面都至关重要。由于这些值在我的 Site.Master 中使用,因此我创建了一个抽象 SiteController 类,该类重写 OnActionExecuting 方法,以为解决方案中每个控制器上的每个 Action 方法填充这些值。

[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);

  }
}

我面临的问题是,当 HandleErrorAttribute 从 SiteController 类级别属性启动时,这些值不会传递给 MyErrorView (最终传递给 Site.Master)。这是一个简单的场景来显示我的问题:

public class TestingController : SiteController
{
  public ActionResult DoSomething()
  {
    throw new MyException("pwnd!");
  }
}

我也尝试通过重写 SiteController 中的 OnException() 方法来填充 ViewData 参数,但无济于事。 :(

在这种情况下,将 ViewData 参数传递到我的 Site.Master 的最佳方法是什么?

In my Site.Master file, I have 3 simple ViewData parameters (the only 3 in my entire solution). These ViewData values are critical for every single page in my application. Since these values are used in my Site.Master, I created an abstract SiteController class that overrides the OnActionExecuting method to fill these values for every Action method on every controller in my solution.

[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);

  }
}

The problem that I'm faced with is that these values are not being passed to MyErrorView (and ultimately Site.Master) when the HandleErrorAttribute kicks in from the SiteController class level attribute. Here is a simple scenario to show my problem:

public class TestingController : SiteController
{
  public ActionResult DoSomething()
  {
    throw new MyException("pwnd!");
  }
}

I've tried filling the ViewData parameters by overriding the OnException() method in my SiteController as well, but to no avail. :(

What is the best way to pass the ViewData parameters to my Site.Master in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

☆獨立☆ 2024-08-19 12:06:43

这是因为当发生错误时,HandleErrorAttribute 会更改传递给视图的 ViewData。它传递一个 HandleErrorInfo 类的实例,其中包含有关 Exception、Controller 和 Action 的信息。

您可以做的就是将此属性替换为下面实现的属性:

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;
            }
        }
    }
}

This is because HandleErrorAttribute changes the ViewData passed to the view when an error occurs. It passes an instance of HandleErrorInfo class with information about Exception, Controller and Action.

What you can do is replace this attribute with the one implemented below:

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;
            }
        }
    }
}
相思故 2024-08-19 12:06:43

如果您只需要通过 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);
    }

请参见此处:如何在错误中使用通过过滤器放入 ViewBag 中的数据.cshtml 视图?

If you just need to pass something via ViewBag it can be done like this: (this happens to be in a BaseController all my controllers inherit from)

    protected override void OnException(ExceptionContext filterContext)
    {
        try
        {
            var v = filterContext.Result as ViewResult;
            v.ViewBag.DataToPassToError = "Hello World!";
        }
        catch { /* no-op */ }

        base.OnException(filterContext);
    }

See Here: How can I use data placed into a ViewBag by a filter in my Error.cshtml view?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文