Asp.net-Mvc

如何將 ViewData 傳遞給 HandleError 視圖?

  • January 18, 2016

在我的 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 的最佳方法是什麼?

這是因為當發生錯誤時,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;
           }
       }
   }
}

引用自:https://stackoverflow.com/questions/1794936