2016-05-13 3 views
0

私はカスタムModelMetadataProviderを試しています。 TextBoxForのようなHTMLヘルパーのいくつかは、これらをうまく使っているようです。しかし、DropDownListForのような他のケースでは、代わりにViewDataを使用します。例えば、私が見るいくつかの反射のコードを見て:HtmlHelperのメタデータとViewData

bool flag = false; 
    if (selectList == null) 
    { 
    selectList = SelectExtensions.GetSelectData(htmlHelper, name); 
    flag = true; 
    } 
    object defaultValue = allowMultiple ? htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string[])) : htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string)); 
    if (defaultValue == null && !string.IsNullOrEmpty(name)) 
    { 
    if (!flag) 
     defaultValue = htmlHelper.ViewData.Eval(name); 
    else if (metadata != null) 
     defaultValue = metadata.Model; 
    } 

する「はdefaultValue」を得るためにすべての異なる試みを注意してください。メタデータを使用しています。モデルは最後に死んでいます。なぜここで分離するのですか?そのコードをトレースすると、最終的にViewData.Evalの呼び出しで終了します。これは、フォールバックとして、リフレクションを使用してモデルの値を取得します。そのギャップを橋渡しするカスタムViewDataプロバイダのようなものはありますか?

編集:これはフレームワークのバグであるという考えに傾き始めています。上記のコードは、オプション "Model.ShiftOptions" に通過

@Html.DropDownListFor(model => model.ErrorData.Shift, Model.ShiftOptions, new { @class = "form-control" }) 

は、2つのコード片を考えます。このため、条件 "selectList == null"を渡すことはなく、結果として "flag"は設定されず、リフレクション(Eval呼び出し)を介してタイプのみからデフォルト値を取得しようとします。しかし、このコードで

は:

@{ ViewData[Html.NameFor(m => m.ErrorData.Shift).ToString()] = Model.ShiftOptions;} 
@Html.DropDownListFor(model => model.ErrorData.Shift,null, new { @class = "form-control" }) 

...「フラグが」今、満足され、デフォルト値は現在metadata.Modelを取得しています。なぜリストオプションを提供するためのさまざまなメカニズムが、デフォルト値がどこから取得されるのか(あるいはそれに影響する)

答えて

1

最初のフォームコントロールを生成するための全てHtmlHelper方法(参照フォームが無効な値で送信されたビューが返される場合を処理するModelStateにおけるプロパティの値(GetModelStateValue()方法)があるかどうかを確認なぜこれがデフォルトの動作であるのかについてはthis answerの第2部を参照してください)。例えばxxxViewBagプロパティとして追加されているIEnumerable<SelectListItem>ある

@Html.DropDownList("xxx", null, "--Please select--") 

ためあなたがDropDownList()を使用する場合に

は、selectListの値はnullであり、第一ifブロック内のコードが実行されflagの値がtrueであることを確認してください(モデルにはxxxという名前のプロパティがある場合もあれば、metadatanullの場合もあります)

あなたが使用される場合

代わりに、強くselectListの値とflagの値がfalse

ある( SomePropertyListIEnumerable<SelectListItem>nullないと仮定) nullない例

@Html.DropDownListFor(m => m.SomeProperty, Model.SomePropertyList, "--Please select--") 

ため、DropDownListFor()方法を入力

したがって、DropDownList()またはDropDownListFor()のいずれかを使用して<select> elを生成するさまざまな方法を考慮していますモデルプロパティにバインドするかどうかを指定します。

サイドノート:(private static MvcHtmlString SelectInternal()メソッドからの)実際のコードは、偉大な答えをしませbool flag = false;

+0

おかげbool usedViewData = false;です。しかし、私はGetModelStateValueが何をしているのか、それが基礎となる辞書が作成されているのかは分かりませんが、メタデータに何が含まれているかはわかりません。私のメタデータプロバイダのCreateMetadataメソッドでは、返されるModelMetadata.Modelプロパティ== "test"を設定できます。 "TextBoxFor"を呼び出すと、テキストボックスはすべて "test"で埋められます。これは何らかの理由でDropDownListForを満たすものではなく、基本的には型に基づいてプロパティのデフォルト値を取得しようとするViewData.Evalを引き続き呼び出します。 –

+0

あなたは私がリンクした答えを読んだのですか? 'ModelState'から値を取得するために' GetModelStateValue() 'が常に最初に呼び出されます(例えばコントローラメソッドにモデルをポストした場合、提出された値は' ModelState'に追加され、ビューを返すと、 –

+0

いいえ、私は賛美する、私は今までリンクに気付かなかった。しかし、私はそれが適切であるかどうかはわかりません。 ModelState.Clearで強制的に強制することができると推測しているモデル状態からの検索が失敗した後も、ViewData.Eval(メタデータから値を取得する代わりに、タイプのリフレクションコールにかかります)を呼び出して呼び出します。 ?他のヘルパーがメタデータを好む場合、DropDownListがタイプを優先させるのはなぜですか? –

関連する問題