ViewModel 的列表在操作中为空 [英] ViewModel's list is null in action

查看:24
本文介绍了ViewModel 的列表在操作中为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发我的第一个 ASP.NET MVC 3 应用程序,我有一个如下所示的视图:

@model IceCream.ViewModels.Note.NotesViewModel@using (Html.BeginForm()){@Html.ValidationSummary(true)@Html.TextBoxFor(m => m.Name)foreach(Model.Notes 中的 var 项目){@Html.EditorFor(m => item);}<input type="submit" value="Submit"/>}

我有一个像这样的 EditorTemplate:

@model IceCream.ViewModels.Note.NoteViewModel<div>@Html.HiddenFor(m => m.NoteID)@Html.TextBoxFor(m => m.NoteText)@Html.CheckBoxFor(m => m.IsChecked)

NotesViewModel 看起来像这样:

 公共类 NotesViewModel{公共字符串名称 { 获取;放;}公共 IEnumerable注释 { 得到;放;}}

NoteViewModel 看起来像这样:

公共类 NoteViewModel{公共 int NoteID { 获取;放;}公共 System.DateTime 时间戳 { 获取;放;}公共字符串 NoteText { 获取;放;}public bool IsChecked { 获取;放;}}

NotesViewModel 在传递到视图时填充得很好.然而,当点击提交按钮时,处理帖子的控制器动作只有视图模型的 Name 属性的值.Notes 属性 - 已被用户选中/取消选中的注释列表 - 为空.我在显示视图时填充这些 TextBoxFor 和 CheckBoxFor 元素与发回 ViewModel 之间存在脱节.这方面的指导?

<小时>

解决方案感谢 Mystere Man 让我直截了当.据我了解,主要是通过将我的循环更改为

@Html.EditorFor(m => m.Notes)

更改了底层 HTML,据我所知,它为帖子提供了正确的模型绑定.查看生成的 HTML,我看到我为其中一个注释生成了以下内容:

<input id="Notes_0__NoteId" type="hidden" value="1" name="Notes[0].NoteId"><input id="Notes_0__NoteText" type="text" value="甜点的质地很好."name="Notes[0].NoteText"><input id="Notes_0__IsChecked" type="checkbox" value="true" name="Notes[0].IsChecked>

这与我的原始代码生成的 HTML 不同:

<input id="item_NoteId" type="hidden" value="1" name="item.NoteId><input id="item_NoteText" type="text" value="甜点的质地很好."name="item.NoteText" ><input id="item_IsChecked" type="checkbox" value="true" name="item.IsChecked">

通过循环遍历注释,生成的 HTML 基本上丢失了对视图模型的注释属性的任何引用,虽然 HTML 被正确填充,但复选框值的设置无法将它们的值传递回视图模型,我猜是模型绑定的点.

所以我学到了一些东西,这很好.

解决方案

你是个聪明人,所以看看你的观点.然后,考虑如何生成 HTML.然后,考虑模型绑定器在回发时如何根据生成的 HTML 重新填充注释.

我想您会发现您的 HTML 中没有足够的信息供 Model Binder 解决.

考虑一下:

@EditorFor(m => Model.Notes)

而不是基本上对 EditorFor 函数隐藏上下文的 for 循环.

I'm working on my first ASP.NET MVC 3 application and I've got a View that looks like this:

@model IceCream.ViewModels.Note.NotesViewModel
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    @Html.TextBoxFor(m => m.Name)

    foreach (var item in Model.Notes)
    {
        @Html.EditorFor(m => item);
    }

    <input type="submit" value="Submit"/>
}

And I have an EditorTemplate that looks like this:

@model IceCream.ViewModels.Note.NoteViewModel
<div>
    @Html.HiddenFor(m => m.NoteID)
    @Html.TextBoxFor(m => m.NoteText)
    @Html.CheckBoxFor(m => m.IsChecked)
</div>

NotesViewModel looks like so:

    public class NotesViewModel
    {
        public string Name { get; set; }
        public IEnumerable<NoteViewModel> Notes { get; set; }
    }

NoteViewModel looks like this:

public class NoteViewModel
{
    public int NoteID { get; set; }
    public System.DateTime Timestamp { get; set; }
    public string NoteText { get; set; }
    public bool IsChecked { get; set; }
}

The NotesViewModel is populated just fine when it is passed to the view. However when the submit button is clicked, the controller action handling the post has only the value for the Name property of the viewmodel. The Notes property - the list of notes that have been checked/unchecked by the user - is null. I've got a disconnect between the populating of those TextBoxFor and CheckBoxFor elements when the view is displayed and the ViewModel being sent back. Guidance on this?


SOLUTION Thanks go to Mystere Man for setting me straight on this. As I understand it, essentially by changing my loop to

@Html.EditorFor(m => m.Notes)

changes the underlying HTML, which I understand provides for the proper model binding on the post. Looking at the resulting HTML, I see that I get the following generated for one of the Notes:

<div>
  <input id="Notes_0__NoteId" type="hidden" value="1" name="Notes[0].NoteId">
  <input id="Notes_0__NoteText" type="text" value="Texture of dessert was good." name="Notes[0].NoteText">
  <input id="Notes_0__IsChecked" type="checkbox" value="true" name="Notes[0].IsChecked>
</div>

Which is different than this HTML generated by my original code:

<div>
   <input id="item_NoteId" type="hidden" value="1" name="item.NoteId>
   <input id="item_NoteText" type="text" value="Texture of dessert was good." name="item.NoteText" >
   <input id="item_IsChecked" type="checkbox" value="true" name="item.IsChecked">
</div>

By looping through the Notes, the generated HTML essentially loses any references to the viewmodel's Notes property and while the HTML gets populated correctly, the setting of the checkbox values has no way to communicate their values back to the viewmodel, which I guess is the point of the model binding.

So I learned something, which is good.

解决方案

You're a smart guy, so look at your view. Then, consider how the HTML gets generated. Then, consider how on postback the Model Binder is supposed to know to re-populate Notes based on the generated HTML.

I think you'll find that your HTML doesn't have enough information in it for the Model Binder to figure it out.

Consider this:

@EditorFor(m => Model.Notes)

Rather than the for loop where you are basically hiding the context from the EditorFor function.

这篇关于ViewModel 的列表在操作中为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆