2012-12-18 42 views
2

我目前正在为我的项目编写一个编辑功能,而且我似乎无法获得视图模型的权利以允许它从视图传回控制器。视图模型的结构是这样的:将复杂的ViewModel传递给MVC中的HttpPost方法3

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 
} 

子类视图模型CreateUserItemViewModel

public class CreateUserItemViewModel : ICreateUserItemViewModel 
{ 
    public string Name { get; set; } 
    public int ID { get; set; } 
    public bool IsSelected { get; set; } 
} 

我想要这个子类中的视图作为一个框来表示,因此用户可以选择包括它与否。

用户控制器:

[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> 

我一直在这对相当长一段时间,我开始认为我想要做的事是不可能的。我希望它返回CreateUserViewModel完全填充用户选择的所有值,但我只是不知道如何实现此目的。

任何想法?

回答

6

使用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 }) 
} 

你的属性表达式需要包含的模型绑定足够的信息来弄清楚如何将POST值绑定到模型。

您也可以尝试为ICreateUserItemViewModel创建编辑器模板,然后将标记更改为以下内容。

@Html.EditorFor(model => model.Products) 
+1

我喜欢EditorFor的方法 –

+0

这工作,我很感激。你会不会解释为什么我需要一个for循环而不是foreach?我觉得我对数据如何传回控制器缺乏基本的了解。 – stuartmclark

+0

使用“for”循环,索引应用于允许将发布列表绑定到viewmodel的项目列表。例如,发布的值将为... products [0] .ID = 1&products [0] .Is Selected = true&products [1]。ID = 2&产品[2] .IsSelected =真。请检查介绍我已发布模型绑定文章的更多信息。 – Sunny

1

如发布答案已经提到的,它可以通过应用索引来进行,但如果这些元素非顺序参考以下文章

http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

另请参阅下面的一个介绍“模式结合”

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

添加到建议列表,考虑删除视图模型中的CreateUserViewModel(列出产品,列表语言)。 ViewModel应该只包含属性,并在控制器内部放置额外的逻辑(即在你的情况下附加UserTypes等)。

相关问题