【问题标题】:mvc5 model which is posted with html.beginform is missing some properties使用 html.beginform 发布的 mvc5 模型缺少一些属性
【发布时间】:2015-01-08 04:22:07
【问题描述】:

我在视图中使用了这个模型:

using (var db = new FieldSaverContext())
{
    AspNetUser user = (from p in db.AspNetUsers
                       where p.Id == id
                       select p).Include(m => m.AspNetRoles) .First();
    model.AUser = user;

    List<AspNetRole> roles = (from r in db.AspNetRoles
                              select r).ToList();
    model.RoleList = roles;

    List<ListID> ids = (from l in db.ListIDs
                        select l).ToList();
    model.ListIDList = ids;

    List<ViewerList> viewerLists = (from v in db.ViewerList
                                    select v).ToList();
    model.ViewerList = viewerLists;

}

这就是我的视图:

@using (Html.BeginForm("Edit", "Users"))
{
  <div class="container containerEdit">
    <div class="col-md-9">
      <div class="col-md-6">
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.Id)
          <label>@Html.DisplayFor(m => m.AUser.Id)</label>
        </div>
        <div class="form-group">
          @Html.DisplayFor(m => m.AUser.FirstName)
          @Html.TextBoxFor(m => m.AUser.FirstName)
        </div>
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.PhoneNumber)
          @Html.TextBoxFor(m => m.AUser.PhoneNumber)
        </div>
        <div class="form-group">
          @Html.LabelFor(m => m.ListIDList)
          @Html.DropDownListFor(n => n.ListIDList, new SelectList(Model.ListIDList, "ID", "Value"))
        </div>
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.Note1)
          @Html.TextBoxFor(m => m.AUser.Note1)
        </div>
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.Note2)
          @Html.TextBoxFor(m => m.AUser.Note2)
        </div>
      </div>
      <div class="col-md-6">
        <div class="form-group">&nbsp;</div>
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.LastName)
          @Html.TextBoxFor(m => m.AUser.LastName)
        </div>
        <div class="form-group">
          @Html.LabelFor(m => m.AUser.Email)
          @Html.TextBoxFor(m => m.AUser.Email)
        </div>
        <div class="form-group">
          <label>Report Viewer</label>
          @Html.DropDownListFor(v => v.AUser.ViewerId, new SelectList(Model.ViewerList, "ID", "Value"))
        </div>
      </div>
      @Html.HiddenFor(v => v.AUser.Id)
    </div>
    <div class="col-md-3">
      @foreach (AspNetRole role in Model.RoleList)
      { @Html.CheckBox(role.Name, Model.AUser.AspNetRoles.Any(userRole => userRole.Id == role.Id)) @Html.Label(role.Name)<br /> }
    </div>
  </div>
  <div class="col-md-8">
    <input type="submit" class="btn btn-success btn-lg btnSaveEdit" value="Save" />
  </div>
}  

当回发发生时,我能够获取 AUser 的值,但我没有获取复选框中使用的 Model.RoleList 的任何值。 我想检查从 RoleList 中选中了哪些复选框并将这些角色分配给用户。

我错过了什么?

更新

编辑操作:

[HttpGet]
public ActionResult Edit(int? id)
{
    ManageViewModel model = new ManageViewModel();

 
        using (var db = new DbContext())
        {
            AspNetUser user = (from p in db.AspNetUsers
                               where p.Id == id
                               select p).Include(m => m.AspNetRoles) .First();
            model.AUser = user;

            List<AspNetRole> roles = (from r in db.AspNetRoles
                                      select r).ToList();

            model.RoleList = roles;

            List<ListID> ids = (from l in db.ListIDs
                select l).ToList();

            model.ListIDList = ids;

            List<ViewerList> viewerLists = (from v in db.ViewerList
                select v).ToList();

            model.ViewerList = viewerLists;

        }
    return View(model);
}

[HttpPost]
public ActionResult Edit(ManageViewModel model)
{
    AspNetUser user = model.AUser;

    using (var db = new DbContext())
    {
        AspNetUser dbUser = (from u in db.AspNetUsers
            where u.Id == model.AUser.Id
            select u).First();

        dbUser.FirstName = model.AUser.FirstName;
        dbUser.LastName = model.AUser.LastName;
        dbUser.Email = model.AUser.Email;
        dbUser.PhoneNumber = model.AUser.PhoneNumber;

        dbUser.Note1 = model.AUser.Note1;
        dbUser.Note2 = model.AUser.Note2;
        dbUser.ViewerId = model.AUser.ViewerId;

        db.SaveChanges();
    }

    return View();
}

【问题讨论】:

  • 您是否检查过model.RoleList 实际上不为空?
  • 好的,你说的“我没有得到 Model.RoleList 的任何值”到底是什么意思?是没有生成标记还是复选框值不正确?
  • 当我单击提交按钮时,在控制器中我无法获取 Model.RoleList 的值,它的值为 null @Groyoh。
  • 哦,我想我明白了。您能否编辑您的问题以显示Edit 操作?一旦我有了它,我会发布一个可能会解决您的问题的答案。

标签: c# asp.net asp.net-mvc asp.net-mvc-4 asp.net-mvc-5


【解决方案1】:

问题是角色没有绑定到您的视图模型。所以这就是你必须做的:

  • 创建一个新的角色视图模型:

    public class RoleViewModel
    {
      public int Id { get; set; }   
      public string Name { get; set; }
      public bool Selected { get; set; }
    }
    
  • 修改您的ManageUserViewModel 以拥有RoleViewModel 的列表而不是AspNetRole

    public class ManageUserViewModel
    {
      public List<RoleViewModel> Roles { get; set;}
      // Your other properties
    }
    
  • 更改您的编辑以从可用角色中设置Roles 属性:

    public ActionResult Edit(int? id)
    {
       // beginning of your action
       List<AspNetRole> roles = from r in db.AspNetRoles
                                select r;
       model.Roles = new List<RoleViewModel>();
       foreach(AspNetRole role in roles){
         model.Roles.Add(new RoleViewModel { 
           Id = role.Id, 
           Name = role.Name,
           Selected = user.AspNetRoles.Any(userRole => userRole.Id == role.Id)
         });
       }
       // end of your action
    }
    
  • 将您的其他操作更改为

     public ActionResult Edit(ManageViewModel model){
      // beginning of your action
      // remove roles from user
      List<AspNetRoles> newRoles = new List<AspNetRoles>();
      foreach(RoleViewModel role in model.Roles){
        newRole.Add(db.AspNetRoles.Find(role.id))
      } 
      // set your user roles from newRoles
      // end of your action 
    }
    
  • 在您看来,将复选框部分更改为:

    @Html.EditorFor(model => model.Roles)
    
  • 最后创建一个Shared/EditorTemplate/RoleViewModel.cshtml 文件:

    @model RoleViewModel
    @Html.HiddenFor(model => model.Id)
    @Html.CheckBoxFor(model => model.Selected)
    @Html.DisplayFor(model => model.Name)
    

【讨论】:

  • 这就是我使用你的例子得到的复选框:gyazo.com/d30dfd748c8218554071230091eec6ef
  • 我的回答打错了。将 EditorTemplate 文件夹更改为 EditorTemplates 并添加一个 's' 并确保此文件夹位于 Views/Shared 文件夹中。
  • 感谢@Groyoh,您的解决方案帮助了我。
【解决方案2】:
  1. for循环替换你的@foreach (AspNetRole role in Model.RoleList)

  2. 重构您的 AspNetRole viewModel 以包含 Selected 属性

    public class AspNetRole
    {
       public int Id { get; set; }   
       public string Name { get; set; }
       public bool Selected { get; set; } // <- new property
    }
    
  3. 从你的ViewModel中删除AspNetRoles

  4. 您将在表单帖子中收到所选项目的列表

查看示例https://dotnetfiddle.net/QbUxi0

【讨论】:

  • 相同的 null @max-brodin
  • @Laziale 编辑答案
  • AspNetRole 表中不存在新属性“Selected”,它是 Asp.Net Identity 的一部分,我应该手动添加该列吗?汉克斯
  • 我认为最好的解决方案是引入新的类RoleViewModelUserViewModel并将Model类转换为ViewModel
  • 您知道为什么使用当前代码我无法获取角色值但我能够获取用户值吗?谢谢
猜你喜欢
  • 1970-01-01
  • 2015-03-11
  • 2015-01-02
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多