2009-11-25 8 views
13

私のSite.Masterファイルには、3つのシンプルなViewDataパラメータがあります(私のソリューション全体では3つしかありません)。これらのViewData値は、アプリケーションのすべての単一ページで重要です。これらの値は私のSite.Masterで使用されているので、OnActionExecutingメソッドをオーバーライドする抽象的なSiteControllerクラスを作成して、私のソリューションのすべてのコントローラ上のすべてのActionメソッドに対してこれらの値を設定します。ViewDataをHandleError Viewに渡すにはどうすればよいですか?

[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をパラメータを充填しようとしたが、無駄にしました。 :(

この場合には、私のSite.MasterにViewDataをパラメータを渡すための最良の方法は何ですか?

答えて

19

HandleErrorAttributeは、エラーが発生したときのViewDataビューに渡さ変わるためです。それはのインスタンスを渡します。例外、コントローラとアクションに関する情報をHandleErrorInfoクラス

何ができるかは以下の実装1と、この属性を置き換えるです:

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

+1

これは実際には機能しません... – fearofawhackplanet

+0

「機能しません」は特に有用ではありません。私は私と他の人のためにやった。使用しているMVCのバージョンを確認する必要があります。私は多くの変更があったと確信しています。 –

3

あなただけ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?

関連する問題