C# 在MVC 3中将复杂的ViewModel传递给HttpPost方法

C# 在MVC 3中将复杂的ViewModel传递给HttpPost方法,c#,asp.net-mvc,C#,Asp.net Mvc,我目前正在为我的项目开发一个编辑功能,我似乎无法正确获取视图模型,以允许它从视图传递回控制器。视图模型的结构如下所示: public class CreateUserViewModel : ICreateUserViewModel { #region Properties public string UserName { get; set; } public string Password { get; set; } public string Email { g

我目前正在为我的项目开发一个编辑功能,我似乎无法正确获取视图模型,以允许它从视图传递回控制器。视图模型的结构如下所示:

public class CreateUserViewModel : ICreateUserViewModel
{
    #region Properties
    public string UserName { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string SelectedUserType { get; set; }
    public List<ICreateUserItemViewModel> UserTypes { get; set; }
    public List<ICreateUserItemViewModel> Products { get; set; }
    public List<ICreateUserItemViewModel> Languages { get; set; }
    #endregion

    #region Constructor
    public CreateUserViewModel()
    {
    }

    public CreateUserViewModel(List<Product> products, List<Language> languages)
    {
        Products = new List<ICreateUserItemViewModel>();
        foreach (var prod in products)
        {
            var prodVM = new CreateUserItemViewModel
            {
                Name = prod.Name,
                IsSelected = false,
                ID = (int)prod.ID
            };
            Products.Add(prodVM);
        }

        Languages = new List<ICreateUserItemViewModel>();
        foreach (var lang in languages)
        {
            var langVM = new CreateUserItemViewModel
            {
                Name = lang.Name,
                IsSelected = false,
                ID = (int)lang.ID
            };
            Languages.Add(langVM);
        }

    }
    #endregion
}
我希望这个子类在视图中表示为一个复选框,以便用户可以选择是否包含它

用户控制器:

[HttpPost]
public ActionResult Create(CreateUserViewModel model)
{
    if (ModelState.IsValid)
    {
        User newUser = new User();
        newUser.UserName = model.UserName;
        newUser.Password = model.Password;
        newUser.Email = model.Email;
        newUser.Products = model.Products; //Always NULL
当我在应用程序的这一部分设置断点时,用户名、密码和电子邮件的属性会被填充,但产品和语言是空的。我使用Fiddler2观察传入控制器的内容,这是输出:

UserName=asdasdsdasd&Password=asd&Email=asD%40asd.com&type.IsSelected=Admin
&prod.ID=1&prod.IsSelected=true&prod.IsSelected=false
&prod.ID=2&prod.IsSelected=false
&prod.ID=3&prod.IsSelected=false
&prod.ID=4&prod.IsSelected=false
&lang.ID=1&lang.IsSelected=true&lang.IsSelected=false
&lang.ID=2&lang.IsSelected=true&lang.IsSelected=false
&lang.ID=3&lang.IsSelected=false
&lang.ID=4&lang.IsSelected=false
&lang.ID=5&lang.IsSelected=false
&lang.ID=6&lang.IsSelected=false
&lang.ID=7&lang.IsSelected=false
&lang.ID=8&lang.IsSelected=false
&lang.ID=9&lang.IsSelected=false
&lang.ID=10&lang.IsSelected=false
&lang.ID=11&lang.IsSelected=false
&lang.ID=12&lang.IsSelected=false
&lang.ID=13&lang.IsSelected=false
&lang.ID=14&lang.IsSelected=false
&lang.ID=15&lang.IsSelected=false
&lang.ID=16&lang.IsSelected=false
&lang.ID=17&lang.IsSelected=false
&lang.ID=18&lang.IsSelected=false
&lang.ID=19&lang.IsSelected=false
“创建”视图的代码要点是:

<div class="editor-label">
    @Html.Label("User Products:")
</div>
<div class="editor-field">
    @foreach (var prod in Model.Products)
    {
        @Html.Label(prod.Name)
        @Html.HiddenFor(x => prod.ID)
        @Html.CheckBoxFor(x => prod.IsSelected, new { name = prod.Name })
    }
</div>
<div class="editor-label">
    @Html.Label("User Languages:")
</div>
<div class="editor-field">
    @foreach (var lang in Model.Languages)
    {
        @Html.Label(lang.Name)
        @Html.HiddenFor(x => lang.ID)
        @Html.CheckBoxFor(x => lang.IsSelected, new { name = lang.Name })
    }
</div>
<p>
    <input type="submit" value="Create" />
</p>

@标签(“用户产品:”)
@foreach(模型产品中的var产品)
{
@Html.Label(prod.Name)
@Html.HiddenFor(x=>prod.ID)
@CheckBoxFor(x=>prod.IsSelected,new{name=prod.name})
}
@Label(“用户语言:”)
@foreach(Model.Languages中的var lang)
{
@Html.Label(lang.Name)
@Html.HiddenFor(x=>lang.ID)
@CheckBoxFor(x=>lang.IsSelected,新的{name=lang.name})
}

我已经为此工作了相当长的一段时间,我开始认为我正在尝试做的是不可能的。我希望它返回
CreateUserViewModel
完全填充了用户选择的所有值,但我不知道如何实现这一点


有什么想法吗?

用for循环代替foreach

@for (int i=0; i < Model.Products.Count; i++)
{
    @Html.Label(prod.Name)
    @Html.HiddenFor(model => model.Products[i].ID)
    @Html.CheckBoxFor(model => model.Products[i].IsSelected, new { name = prod.Name })
}

正如在发布的答案中已经提到的,可以通过应用索引来完成,但如果元素是非顺序的,请参阅下面的文章

关于“模型绑定”的介绍,请参见下文


添加到建议列表中,考虑从VIEW模型中删除CurtAutoReVIEW模型(列表产品、列表语言)。ViewModel应该只包含属性,并在控制器中放置额外的逻辑(例如,在您的情况下,附加用户类型等)。

我喜欢编辑器的方法。对于这种方法的有效性,我非常感谢。你能解释一下为什么我需要for循环而不是foreach吗?我觉得我对如何将数据传回控制器缺乏基本的了解。使用“for”循环,将索引应用于项目列表,允许将发布的列表绑定到viewmodel。对于ex,过帐值将为…产品[0]。ID=1和产品[0]。IsSelected=true和产品[1]。ID=2和产品[2]。IsSelected=true。有关更多信息,请查看我发布的《模型绑定简介》一文。@stuartmclark,要了解模型绑定到集合的工作原理,请查看Sundeep提供给您的链接,这里您还有几条:,谢谢!我在这上面浪费了半天!
@for (int i=0; i < Model.Products.Count; i++)
{
    @Html.Label(prod.Name)
    @Html.HiddenFor(model => model.Products[i].ID)
    @Html.CheckBoxFor(model => model.Products[i].IsSelected, new { name = prod.Name })
}
@Html.EditorFor(model => model.Products)