【问题标题】:MVC3 Html.Editor targeting dictionary is not binding down to the clientMVC3 Html.Editor 目标字典未绑定到客户端
【发布时间】:2011-03-24 19:46:00
【问题描述】:

我的视图模型是这样的

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++;
    }
}

正如我所期望的那样,它会在编辑屏幕上呈现一系列键值对文本框。但是,即使 Claims 字典中有 KeyValuePairs,文本框也始终为空。

如果我填写 KVP 文本框的值并将表单发回我的控制器,我确实可以将值正确地模型绑定到我的 User.Claims 字典中。

我错过了什么导致绑定在视图加载时无法在其中包含正确的值?

编辑: 附加信息,基本上我试图弄清楚这对于 MVC 究竟是如何工作的。我直接从 Brad Wilson discusses here 的核心 MVC (2) 对象模板创建了上面的视图。我试图在 Razor 中找到确切的代码,但我在任何地方都找不到它……离题了……将它转换为 Razor 我最终得到了

@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 &gt; 4) 的编辑,这将允许 MVC 深入到我的字典中,然后可以正确绑定所有内容。然而,在进一步询问调试后,我看到它何时绑定了它实际上只看到 @Html.Editor("Key") 的 Key 属性,这是如何工作的?

显然编辑器必须对 ViewData.ModelMetadata.Properties 有某种了解,但是它确定 ViewData.TemplateInfo.Visited() 的结果是它能够正确放置正确的东西,就在这一点上,我处于失去了在 @Html.Editor("Key") 做任何事情的这个 foreach 循环内部发生的事情。

【问题讨论】:

    标签: asp.net-mvc-3 dictionary model-binding


    【解决方案1】:

    试试这样:

    @{
        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++;
        }
    }
    

    【讨论】:

    • 这确实有效,但仍然无法解释为什么编辑器语法不起作用,因为我基本上是在尝试模拟 MVC 中直接发生的事情,当您更改对象编辑器模板以进行深度操作时深入研究模型,对象编辑器模板中的整个代码主要由 @Html.Editor(prop.PropertyName) 组成
    • @Chris Marisic,您的代码不起作用的原因是您没有将任何模型值传递给编辑器模板。您只是使用User.Claims[i].Key 语法,但默认模型绑定器使用该语法作为输入参数,而不是帮助器在获取值时作为输出。我个人建议您避免在视图模型中使用字典,并将其替换为自定义类型列表。
    • 我不明白我在这里的使用与 bradwilson.typepad.com/blog/2009/10/… 的 EditorTemplates/Object.ascx 部分中所见的固有工作方式有何不同@ 他们在这里拥有的对象模板没有别的比属性名称(功能方面),我不确定为什么这段代码会绑定它而不是我的代码。我看不出两者之间如何存在任何上下文差异。此外,除了大多数自定义列表将具有比键/值更多的属性之外,我也没有看到与此和自定义列表相关的任何差异。
    • 我收回我没有看到任何上下文差异的声明,我曾假设通过调试我实际上会看到“property.Name”评估为索引字符串值,但它只是没有任何类型索引器的键,很奇怪。
    【解决方案2】:

    @Html.Editor(string name) 将为ViewData中的字段名生成编辑器。如果 ViewData 不包含您的对象,则必须使用另一个重载:@Html.Editor(string name, object viewData)。

    在您的情况下,您可以将 @Html.Label(string.Format("User.Claims[{0}].Key", i)) 替换为 @Html.Label(string.Format("User.Claims[ {0}].Key", i),User.Claims[i].Value)

    【讨论】:

    • 非常有趣,我会在周一早上赏金到期前先检查一下!
    • 这绝对是在正确的轨道上,我还没有弄清楚到底要插入到对象 AdditionalViewData 中
    • ASP.NET MVC是开源的,可以查看源码了解背景。
    【解决方案3】:
       @{
     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>
    
     }
        }
    

    【讨论】:

      猜你喜欢
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 2011-03-16
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 2023-04-10
      相关资源
      最近更新 更多