2011-12-24 56 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

相關問題