いくつかの特殊なケースでは、実行前に ID がわからないテキストボックスのリスト (n - n 関連付けを処理するため) が必要になります。このようなもの: http://screencast.com/t/YjIxNjUyNmU
その特定のサンプルでは、カウントをいくつかの「テンプレート」に関連付けようとしています。
ASP.Net MVC 1では、Dictionary ModelBinder をコーディングして、クリーンで直感的な HTML を作成しました。次のようなことが許可されました:
// loop on the templates
foreach(ITemplate template in templates)
{
// get the value as text
int val;
content.TryGetValue(template.Id, out val);
var value = ((val > 0) ? val.ToString() : string.Empty);
// compute the element name (for dictionary binding)
string id = "cbts_{0}".FormatMe(template.Id);
%>
<input type="text" id="<%= id %>" name="<%= id %>" value="<%= value %>" />
<label for="<%= id %>"><%= template.Name %></label>
<br />
バインダーのコードは次のとおりです。
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
IDictionary<int, int> retour = new Dictionary<int, int>();
// get the values
var values = bindingContext.ValueProvider;
// get the model name
string modelname = bindingContext.ModelName + '_';
int skip = modelname.Length;
// loop on the keys
foreach(string keyStr in values.Keys)
{
// if an element has been identified
if(keyStr.StartsWith(modelname))
{
// get that key
int key;
if(Int32.TryParse(keyStr.Substring(skip), out key))
{
int value;
if(Int32.TryParse(values[keyStr].AttemptedValue, out value))
retour.Add(key, value);
}
}
}
return retour;
}
ASP.Net MVC 2に渡すとき、問題はValueProviderがもはや辞書ではないことです。私が行ったように、値をループして解析する方法はありません。
そして、私はそうする他の方法を見つけられませんでした(知っているなら教えてください).
私は最終的に辞書をバインドする「標準」の方法に切り替えましたが、HTML は見苦しく、直観に反し (カウンターを使用してインデックスのないコレクションをループしますか??)、必要な動作とは異なり、すべての値が必要です (そしてそのASP.Net MVC で完全に機能しました 1)。
次のようになります。
int counter= 0;
// loop on the templates
foreach(ITemplate template in templates)
{
// get the value as text
int val;
content.TryGetValue(template.Id, out val);
var value = ((val > 0) ? val.ToString() : string.Empty);
// compute the element name (for dictionary binding)
string id = "cbts_{0}".FormatMe(template.Id);
string dictKey = "cbts[{0}].Key".FormatMe(counter);
string dictValue = "cbts[{0}].Value".FormatMe(counter++);
%>
<input type="hidden" name="<%= dictKey %>" value="<%= template.Id %>" />
<input type="text" id="<%= id %>" name="<%= dictValue %>" value="<%= value %>" />
<label for="<%= id %>"><%= template.Name %></label>
<br />
ModelState
コントローラーでは、「値が必要です」というエラーを回避するために、をだます必要があります。
public ActionResult Save(int? id, Dictionary<int, int> cbts)
{
// clear all errors from the modelstate
foreach(var value in this.ModelState.Values)
value.Errors.Clear();
これは難しすぎます。私はすぐにこの種のバインディングを何度も使用する必要があり、おそらくいくつかの層の開発者がアプリケーションで作業する必要があります。
質問 :
- それをより良くする方法を知っていますか?
私が必要としているのは、IMO は、より良い html を許可し、すべての値が必要であることを考慮しない辞書用の ModelBinder です。