6

ビューモデルが作成されると、ビューモデルのセッタープロパティにオプション(ドロップダウンリストで使用される)を設定できます。 問題は、そのビューモデルが後でパラメータとして(フレームワークによって)アクションメソッドに渡されたときに、それらのプロパティ値が自動的に に再配分されないため、検証エラーのためにフォームを再表示する必要がある場合です。それらのオプションを再投入する必要があります。アクションメソッドパラメータとして使用されるビューモデルインスタンスのコンストラクタインジェクション

MVCフレームワークでコンストラクタインジェクションを使用してビューモデルをインスタンス化する方法は、ビューモデルコンストラクタに何らかの種類のデータアクセスオブジェクトの実装を提供する方法です(例えば、ヘルパーメソッド "DropDownListFor"のように)ビューが要求したときにオプションを取得するために使用できるリポジトリ(リポジトリなど)?

解決策はIModelBinderProviderまたはIModelBinderの実装と関係しているかもしれませんが、ネット上のサンプルコードスニペットからこれらのものを試した後も、完全に動作するサンプルを探しています。ダウンロード可能な実行可能ファイルどのようにすべてのものをまとめるのか分からなくてもコードを書くことができます。

選択リストを作成する方法についての別のディスカッションをお探しの場合は、代わりに「Dependecyインジェクション」の「Dependecy検索」であなたは以下の議論をチェックアウトすることもできます。GET/POST Best way to populate SelectList for ViewModel on GET/POST

上のViewModelのためのSelectListのを移入する 最善の方法を何日か前、私は以下のフォローアップを書きました「Dependecyインジェクション」について、そのスレッドに質問私は今、このスレッドで探しています: しかし

代わりに誰かがなることを期待して(私はの解決策を探しています問題についてのコード例を提供します)https://stackoverflow.com/a/8674525/310457 あまり具体的でないタイトルの古いスレッドを見つけ、私が探しているものについてより具体的なテーマでこの新しい質問を作成しましたr。 また、私が探しているこの特定の解決策に関して、このスレッドからこの新しい質問にフォローアップしたい人のためのリンクを提供します。

答えて

5

私はあなたのViewModelにコンストラクタを介して何かを注入したいと仮定しています。例えば、何を表示するかを決定するためにViewが使う種類の設定オブジェクトです。また、MVCがコントローラインスタンスの引数からモデルインスタンスを自動的に作成してバインドしようとすると、このアプローチによって「このオブジェクトに対して定義されたパラメータなしのコンストラクタがありません」というエラーが発生していると想定しています。また、実行時にSiteConfigオブジェクトをコントローラに自動的に挿入するためにDIフレームワークを使用することを前提とします。

これは、私たちが解決しなければならない唯一の問題は、自動的にバインドされたときにコントローラから注入されたオブジェクトをアクションのViewModelに取得する方法であることを意味します。

他の人が継承するベースモデルを定義しましょう。

BaseViewModel

public class BaseViewModel 
{ 
    public ISiteConfig SiteConfig { get; set; } 

    public BaseViewModel(ISiteConfig siteConfig) 
    { 
     this.SiteConfig = siteConfig; 
    } 
} 

そして今のはそれから継承するモデルを作成してみましょう。

IndexViewModel

public class IndexViewModel : BaseViewModel 
{ 
    public string SomeIndexProperty { get; set; } 

    public IndexViewModel (ISiteConfig siteConfig) : base(siteConfig) {} 
} 

そして今、私たちのコントローラから継承するベースコントローラを定義してみましょう。

BaseController

public abstract class BaseController : Controller 
{ 
    protected BaseController(ISiteConfig siteConfig) 
    { 
     _siteConfig = siteConfig; 
    } 

    private readonly ISiteConfig _siteConfig; 

    public ISiteConfig SiteConfig 
    { 
     get 
     { 
      return _siteConfig; 
     } 
    } 
} 

今、私たちは、実際のコントローラを定義します。私たちはDIのためNinjectを使用していると仮定すると、

public HomeController: BaseController 
{ 
    public HomeController(ISiteConfig siteConfig): base(siteConfig) {} 
} 

にHomeController、Ninjectは自動的にコントローラを作成し、実行時にそのコンストラクタの中に具体的なISiteConfigオブジェクトを渡すように構成されることになります。

ここで、コントローラにアクションを追加します。

indexアクション

public ActionResult Index(IndexViewModel model) 
{ 
    return View(model); 
} 

とMVCができるので、これは」あなたはインデックスアクションを呼び出すようにしようとした場合、他の何もせずに、MVCは「パラメータなしコンストラクタ」エラーで爆発するポイントです引数を取らないViewModelコンストラクタを見つける。

そう、答え。デフォルトのModelBinderをオーバーライドする必要があります。

BaseViewModelBinder

public class BaseViewModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     if (modelType == typeof(BaseViewModel) || modelType.IsSubclassOf(typeof(BaseViewModel))) 
     { 
      var baseControl = controllerContext.Controller as BaseController; 
      if (baseControl == null) 
      { 
       throw new Exception("The Controller must derive from BaseController"); 
      } 

      var instance = Activator.CreateInstance(modelType, baseControl.SiteConfig); 
      bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, modelType); 
      return instance; 
     } 
     else 
     { 
      return base.CreateModel(controllerContext, bindingContext, modelType); 
     } 
    } 
} 

そして、我々はglobal.asax.csのデフォルトのモデルバインダーとしてこれを設定する必要があります。

protected void Application_Start() 
{ 
    ... 
    ModelBinders.Binders.DefaultBinder = new BaseViewModelBinder(); 
} 

すべてです。ご覧のとおり、インデックスアクションを表示すると、MVCはカスタムモデルバインダーを使用します。 IndexViewModelはBaseViewModelから派生しているため、(コントローラがBaseControllerから派生しているため)Actionのコントローラで見つけることができるISiteConfigを使用してIndexViewModelインスタンスをスピンアップしようとします。

+0

ISiteConfigが何であるか分かりません。私はそれを実装する必要がありますか? –

+0

ISiteConfigは、ビューに自動的に挿入するSiteConfigオブジェクトのインターフェイスです。 ISiteConfigとSiteConfigは独自の設定オブジェクトを参照します.Viewに提供したいものは何でも、まさにその例です。 –

関連する問題