2011-03-24 13 views
1

我的視圖模型是沿着MVC3 Html.Editor瞄準字典不結合到客戶端

EditViewModel 
    SomeUserType User 
     Dictionary<string, string> Claims 

線在我看來,我想結合這個如下

@{ 
    int i = 0; 
    foreach (var key in Model.User.Claims.Keys) 
    {                  
      <div class="editor"> 
       <input type="hidden" value="@i" name="User.Claims.Index"> 
       <div class="editor-label"> 
        @Html.Label(string.Format("User.Claims[{0}].Key", i)) 
       </div> 
       <div class="editor-field"> 
        @Html.Editor(string.Format("User.Claims[{0}].Key", i)) 
       </div> 
       <div class="editor-label"> 
        @Html.Label(string.Format("User.Claims[{0}].Value", i)) 
       </div> 
       <div class="editor-field"> 
        @Html.Editor(string.Format("User.Claims[{0}].Value", i)) 
       </div> 
      </div>  
     i++; 
    } 
} 

按照我的預期,在編輯屏幕上呈現出一系列Key Value pair文本框。但是,即使Claim字典中有KeyValuePairs,文本框也始終爲空。

如果我填寫KVP文本框的值並將表單發送回我的控制器,我確實將模型綁定到我的User.Claims字典中。

我錯過了什麼是防止綁定從視圖中加載正確的值?

編輯:附加信息,基本上我想弄清楚這究竟是如何工作的MVC內在。我直接從Brad Wilson discusses here的核心MVC(2)對象模板創建了我的視圖。我試圖找到這在剃刀確切的代碼,但我找不到它的任何地方都題外話... ...這轉換成剃刀我結束了

@if (ViewData.TemplateInfo.TemplateDepth > 4) 
{ 
    @ViewData.ModelMetadata.SimpleDisplayText 
} 
else 
{ 
    <div class="editor">  
     @foreach (var prop in ViewData.ModelMetadata.Properties 
      .Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) 
     {       

      if (prop.HideSurroundingHtml) 
      { 
      @Html.Editor(prop.PropertyName) 
      } 
      else 
      { 
       if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName) 
                  .ToHtmlString())) 
       { 
        <div class="editor-label"> @Html.Label(prop.PropertyName) 
        </div> 
       } 

       <div class="editor-field"> 
        @Html.Editor(prop.PropertyName) 
        @Html.ValidationMessage(prop.PropertyName) 
       </div>    
      } 
     } 
    </div>  
} 

的主要區別是編輯@if (ViewData.TemplateInfo.TemplateDepth > 4)這將允許MVC深入到足以達到我的字典,它可以然後正確地綁定一切。然而,經過進一步的調試與調試,我看到它綁定密鑰屬性時,它實際上只看到@Html.Editor("Key")這是如何工作的?

很明顯,編輯器必須具有某種ViewData.ModelMetadata.Properties的知識,然而它決定了ViewData.TemplateInfo.Visited()的結果是它能夠正確地放置正確的東西,就在此時我在在@Html.Editor(「Key」)執行任何操作的foreach循環內部發生了一些幕後現象。

回答

2

@ Html.Editor(字符串名稱)會產生字段名編輯在ViewData的。如果ViewData不包含您的對象,則必須使用另一個重載:@ Html.Editor(字符串名稱,對象viewData)。你可以用@ Html.Label替換@ Html.Label(string.Format(「User.Claims [{0}] .Key」,i))(string.Format(「User.Claims [{0}] Key「,i),User.Claims [i] .Value)

+0

非常有趣,我將在週一早上檢查出這件事情,在賞金到期之前! – 2011-04-03 17:17:48

+0

這絕對是正確的軌道,我還沒有想出什麼東西插入到對象additionalViewData尚未 – 2011-04-04 13:17:24

+0

ASP.NET MVC是開源的,你可以查看源代碼來知道背景的一切。 – langtu 2011-04-05 04:16:16

3

嘗試這樣的:

@{ 
    var i = 0; 
    foreach (var key in Model.User.Claims.Keys) 
    { 
     <div class="editor"> 
      <input type="hidden" value="@i" name="User.Claims.Index" /> 
      <div class="editor-label"> 
       @Html.Label(string.Format("User.Claims[{0}].Key", i)) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBox(string.Format("User.Claims[{0}].Key", i), key) 
      </div> 
      <div class="editor-label"> 
       @Html.Label(string.Format("User.Claims[{0}].Value", i)) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBox(string.Format("User.Claims[{0}].Value", i), Model.User.Claims[key]) 
      </div> 
     </div>    
     i++; 
    } 
} 
+0

這的確的工作,仍然不能解釋爲什麼編輯器語法不工作時,我基本上試圖模仿MVC中直接發生的事情,當你改變對象編輯器模板來深入研究模型,並且Object編輯器模板中的整個代碼主要由'@ Html.Editor(prop.PropertyName)' – 2011-03-25 12:55:37

+1

@ Chris Marisic ,您的代碼不起作用的原因是您沒有將任何模型值傳遞給編輯器模板。您只需使用User.Claims [i] .Key'語法,但默認模型聯編程序將使用該語法作爲輸入參數,但在獲取值時,輔助程序不會使用該語法作爲輸出。我個人建議你避免在視圖模型中使用字典,並用自定義類型列表替換它們。 – 2011-03-25 13:02:49

+0

我不明白我在這裏的用法與這種工作方式有什麼不同,如在http://bradwilson.typepad上的EditorTemplates/Object.ascx部分中看到的。com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html這裏的對象模板除了屬性名稱之外沒有別的東西(功能明智),我不確定爲什麼會這樣代碼將綁定它,但不是我的代碼。我沒有看到2之間可能存在任何上下文差異。除了大多數自定義列表將具有比鍵/值更多的屬性外,我也沒有看到與此自定義列表的關係有任何差異。 – 2011-03-25 16:27:53

0
@{ 
foreach (KeyValuePair<string, string> item in Model.ShippingCarrier) 
{ 
    <tr> 
    <td> 
    @Html.TextBox(item.Key.ToString(), item.Key, new { @class = "w50" }) : @Html.TextBox(item.Key.ToString(), item.Key, new { @class = "w50" }) 
    </td> 
    </tr> 

} 
    }