2010-05-26 14 views
1

在某些特殊情況下,您需要一個文本框列表(處理n-n個關聯),其編號在運行時不知道。 這樣的事情:http://screencast.com/t/YjIxNjUyNmUASP.Net MVC 2 - 更好的ModelBinding for Dictionary <int, int>

在這個特定的示例中,我期待將計數與我的一些「模板」相關聯。

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很醜陋,違反直覺(使用counter來循環非索引集合??)並且所有的值都是必需的,不像行爲I需要(並且在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(); 

這是太棘手。 我很快就需要多次使用這種綁定,並且可能在應用程序中有一些開發人員的工作。

問:

  • 你知道一種方法,使其更好?

我需要什麼,國際海事組織,是一個ModelBinder字典,允許更好的HTML,並沒有考慮到所有的值都是必需的。

回答

2

您完全可以在MVC 2中繼續使用您的MVC 1模型綁定器。您必須做出的最大改變是您的模型綁定器不應該違背IValueProvider,而應該直接針對Request。形成。您可以枚舉該集合並執行您的特定場景所需的任何邏輯。

IValueProvider接口的目的是提供數據來自何處的抽象,並且是爲通用綁定器(如DefaultModelBinder)提供的。由於數據不能保證可枚舉,因此IValueProvider本身不能是IEnumerable。但在你的特定情況下,如果你有特定場景的特定聯編程序,並且已經知道數據來自表單,則抽象是不必要的。

+0

感謝您的建議。有時回到基礎是關鍵,而且很明顯你看不到它...... – Mose 2010-05-27 08:03:59

相關問題