14

私の Site.Master ファイルには、3 つの単純な ViewData パラメーターがあります (ソリューション全体で 3 つだけです)。これらの ViewData 値は、アプリケーションのすべてのページにとって重要です。これらの値は Site.Master で使用されるため、OnActionExecuting メソッドをオーバーライドして、ソリューション内のすべてのコントローラーのすべての Action メソッドにこれらの値を入力する抽象 SiteController クラスを作成しました。

[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 に渡す最良の方法は何ですか?

4

2 に答える 2

21

これは、エラーが発生すると、HandleErrorAttribute がビューに渡される ViewData を変更するためです。Exception、Controller、および Action に関する情報を含む 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;
            }
        }
    }
}
于 2009-11-25T06:13:41.077 に答える