2011-12-24 53 views
2

我正在使用编辑器模板来显示用户可以分配给每个角色的复选框。该模型是:编辑器模板中的复选框未绑定到发布后的模型

public class UserModel 
{ 
    [Required] 
    [Display(Name = "User name")] 
    public string UserName { get; set; } 

    [Required] 
    [DataType(DataType.EmailAddress)] 
    [Display(Name = "Email address")] 
    public string Email { get; set; } 

    [Required] 
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 
    [DataType(DataType.Password)] 
    [Display(Name = "Password")] 
    public string Password { get; set; } 

    [DataType(DataType.Password)] 
    [Display(Name = "Confirm password")] 
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 
    public string ConfirmPassword { get; set; } 

    public IEnumerable<string> UserRoles { get; set; } 
} 
public class UserRoleModel 
{ 
    public IEnumerable<RoleViewModel> AllRoles { get; set; } 
    public UserModel user { get; set; } 

    public UserRoleModel() 
    { 
     this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
     { 
      Name = r 
     }); 
     this.user = new UserModel(); 
    } 
} 
public class RoleViewModel 
{ 
    public string Name { get; set; } 
    public bool Selected { get; set; } 
} 

控制器:

public ActionResult Create() 
    { 
     return View(new UserRoleModel()); 
    } 

    [HttpPost] 
    public ActionResult Create(UserRoleModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      MembershipCreateStatus createStatus; 
      Membership.CreateUser(model.user.UserName, model.user.Password, model.user.Email, null, null, true, null, out createStatus); 

      if (createStatus == MembershipCreateStatus.Success) 
      { 


       foreach (var r in model.AllRoles) 
       { 
        if (r.Selected) 
        { 
         Roles.AddUserToRole(model.user.UserName, r.Name); 
        } 
       } 

       return RedirectToAction("Index", "Home"); 
      } 
      else 
      { 
       ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
      } 
     } 

     return View(model); 
    } 

的观点:

@model BBmvc.Areas.Tools.Models.UserRoleModel 


@using (Html.BeginForm()) { 
@Html.ValidationSummary(true) 
<fieldset> 
    <legend>UserModel</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.UserName) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.UserName) 
     @Html.ValidationMessageFor(model => model.user.UserName) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.Email) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.Email) 
     @Html.ValidationMessageFor(model => model.user.Email) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.Password) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.Password) 
     @Html.ValidationMessageFor(model => model.user.Password) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.ConfirmPassword) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.ConfirmPassword) 
     @Html.ValidationMessageFor(model => model.user.ConfirmPassword) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(x => x.AllRoles) 
    </div> 


    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 

}

和编辑模板

@model BBmvc.Areas.Tools.Models.RoleViewModel 
@Html.CheckBoxFor(x => x.Selected) 
@Html.LabelFor(x => x.Selected, Model.Name) 
@Html.HiddenFor(x => x.Name) 
<br /> 

问题是,在后期操作中没有区分是否勾选了任何复选框。看起来,它并没有受到模型的约束。

回答

1

你的问题来自推迟执行的LINQ查询。您需要急切地初始化集合:

public class UserRoleModel 
{ 
    public IEnumerable<RoleViewModel> AllRoles { get; set; } 
    public UserModel user { get; set; } 

    public UserRoleModel() 
    { 
     this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
     { 
      Name = r 
     }).ToList(); 
     this.user = new UserModel(); 
    } 
} 

通知的.ToList()电话:

this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
{ 
    Name = r 
}).ToList(); 

而这里的解释。当你写:

this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
{ 
    Name = r 
}); 

在这一刻查询不执行。只有表达式树被构建,但实际查询仅在迭代开始迭代时执行。什么开始迭代?首先是这个观点。在视图中使用编辑器模板这个集合:

@Html.EditorFor(x => x.AllRoles) 

由于AllRoles是一个集合属性ASP.NET MVC将自动迭代,并呈现为集合中的每个元素编辑模板。所以这适用于正确渲染视图。

现在让我们看看表单发布后会发生什么。您发布到创建操作并默认模型联编程序启动。构造函数被调用,但由于没有什么可以遍历AllRoles属性,所以此时不​​执行查询。事实上,它是在行动后面执行的,并且这些值会丢失。

因此,我建议您避免在构造函数中初始化您的视图模型。这将是更好地做到这一点,相应的控制器操作中:

public class UserRoleModel 
{ 
    public IEnumerable<RoleViewModel> AllRoles { get; set; } 
    public UserModel user { get; set; } 
} 

然后:

public ActionResult Create() 
{ 
    var model = new UserRoleModel 
    { 
     AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
     { 
      Name = r 
     }).ToList(), 
     user = new UserModel() 
    }; 
    return View(model); 
} 
+0

好极了!谢谢! – Rob 2011-12-26 14:13:12

相关问题