2016-06-30 6 views
2

アクション結果が実行される前に実行されるカスタムActionFilterを作成しようとしています。この属性は、TempDataに格納されたエラー情報を取得し、強く型付けされた主要モデル内のサブモデル(ErrorModel)に挿入します。しかし、私は、エラーサブモデルを含む異なるモデルタイプを使用するアクションにこれを適用できるようにしたいと考えています。このため、フィルタを特定のViewModelに結びつけることはできません。サブモデルの内容をOnResultExecutingから設定する方法は?

該当する場合、ErrorModelはIEnumerable < ErrorViewModel>です。

これは私のActionFiltersで初めての作業ですので、暗闇の中で撮影しているような気がします。リフレクションにもかなり新しいです。私は秘密が単に適切にナビゲートしていると感じています。

例外の詳細:System.Reflection.TargetException:コード付き

は、以下に示されるように、私は最後の行にエラーを取得していますオブジェクトは、ターゲット・タイプと一致していません。

どのように私は様々なモデル間で共有されるサブモデルに値を挿入するためのActionFilterを使用することができますか?それとも良い方法がありますか?あなたは、本質的に持っている何

public class SetErrorModelAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     var model = filterContext.Controller.ViewData.Model.GetType(); 
     var errorModel = model.GetProperty("ErrorModel"); 
     errorModel.SetValue(errorModel, filterContext.Controller.TempData["Errors"] as IEnumerable<ErrorViewModel>); 
    } 
} 

答えて

0

Type model = filterContext.Controller.ViewData.Model.GetType(); 
PropertyInfo errorModel = model.GetProperty("ErrorModel"); 
errorModel = tempData as IEnumerable<ErrorViewModel> 

例外の詳細を次のとおりです。System.Reflection.TargetException:オブジェクトがターゲット・タイプに

と一致していません。しかし、あなたは、リフレクションをスキップすることができます。ビューモデルに共通のインタフェースを使用し、ビューモデルがそのインタフェースを実装していることを確認することができます。

public interface IErrorViewModel 
{ 
    IEnumerable<ErrorViewModel> Errors { get; set; } 
} 

public MyViewModel : IErrorViewModel 
{ 
    public string Name { get; set; } 
    public IEnumerable<ErrorViewModel> Errors { get; set; } 
} 


public class SetErrorModelAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     IErrorViewModel model = filterContext.Controller.ViewData.Model as IErrorViewModel; 
     model.Errors = filterContext.Controller.TempData["Errors"] as IEnumerable<ErrorViewModel>; 
    } 
} 

と利用

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     TempData["Errors"] = new List<ErrorViewModel> 
     { 
      new ErrorViewModel { ErrorDescription = "Not enough cowbell" }, 
      new ErrorViewModel { ErrorDescription = "Too much cowbell" } 
     }; 

     return RedirectToAction("Error"); 
    } 

    [SetErrorModel] 
    public ActionResult Error() 
    { 
     return View("Index", new MyViewModel { Name = "Cowbell" }); 
    } 
} 
+0

私は理解しておいてくださいするには... filterContext.Controller.ViewData.Modelは喜ん関係なく、それは種類や他のコンテンツだ、IErrorViewModelから派生した任意のモデルを返しません。それからmodel.Errorsはそのサブモデルへのアクセスを許可します。 – Abigail

+1

'filterContext.Controller.ViewData.Model'は、' IErrorViewModel'にキャストする 'Object'型です。ビューモデルがこのインタフェースを実装していると仮定しているため、アクションフィルタでインタフェースのプロパティを使用できます。 – Jasen

+0

ありがとう、それははるかにきれいに感じ、確かに読みやすいです。インターフェイスの柔軟性に感謝しています! – Abigail

関連する問題