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++;
}
}
这将按照我的预期在编辑屏幕上呈现一系列键值对文本框。然而,即使声明字典中有 KeyValuePair,文本框也始终为空。
如果我填写 KVP 文本框的值并将表单发送回我的控制器,我确实会将值正确地模型绑定回我的 User.Claims
字典中。
我错过了什么,导致视图加载时绑定无法获得正确的值?
编辑:附加信息,基本上我试图弄清楚这对于 MVC 本质上是如何工作的。我直接从核心 MVC (2) 对象模板创建了上面的视图 Brad Wilson 在此讨论。我试图在 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 > 4)
这将允许 MVC 深入到我的字典中,然后它可以正确绑定所有内容。然而,经过进一步的调试询问,我发现当它绑定 Key 属性时,它实际上只看到 @Html.Editor("Key")
这是如何工作的?
显然,编辑器必须对 ViewData.ModelMetadata.Properties 有一定的了解,但是它决定了 ViewData.TemplateInfo.Visited() 的结果,即它能够正确放置正确的东西,就在这一点上,我不知道什么是发生在幕后,在这个 foreach 循环内部, @Html.Editor("Key") 做了任何事情。
My view model is along the lines of
EditViewModel
SomeUserType User
Dictionary<string, string> Claims
In my view I'm trying to bind this as follows
@{
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++;
}
}
Which renders out the series of Key Value pair text boxes on the edit screen as I would expect. However the text boxes are always empty even though there are KeyValuePairs in the Claims dictionary.
If I fill in values for the KVP text boxes and post the form back to my controller I do get the values correctly model bound back into my User.Claims
Dictionary.
What am I missing that is preventing the binding from having the correct values in it as the view loads?
Edit: Additional information, basically I'm trying to figure out how exactly this works for MVC inherently. I created my view above directly from the core MVC (2) object template that Brad Wilson discusses here. I tried to find the exact code for this in Razor but I couldn't find it at all anywhere... digressing... Converting this to Razor I ended up with
@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>
}
The main difference is the edit to the @if (ViewData.TemplateInfo.TemplateDepth > 4)
which will allow MVC to dive deep enough that it reaches my dictionary it can then bind everything correctly. However upon further interrogation with debugging I see when it binds the Key property it actually sees just @Html.Editor("Key")
how does this work?
Clearly Editor must have some kind of knowledge of ViewData.ModelMetadata.Properties and however it determines ViewData.TemplateInfo.Visited()'s result that it's able to correctly place the right stuff, just at this point I'm at a loss of what's happening behind the scenes that somehow inside of this foreach loop that @Html.Editor("Key") does ANYTHING.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试这样:
Try like this:
@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)
@Html.Editor(string name) will generate editor for field name in ViewData. If ViewData not contains your object, you must used another overload: @Html.Editor(string name, object viewData).
In your case, you can replace @Html.Label(string.Format("User.Claims[{0}].Key", i)) with @Html.Label(string.Format("User.Claims[{0}].Key", i),User.Claims[i].Value)