POST到MVC控制器IEnumerable的嵌套型号为空时,我没有选择,为了复选框 [英] POST to MVC controller IEnumerable nested Model is null when I don't select checkboxes in order

查看:255
本文介绍了POST到MVC控制器IEnumerable的嵌套型号为空时,我没有选择,为了复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我试图让值后的复选框的值设置为NULL的时候,我不以(1,2,3等),然后检查。

When I'm trying to get values in Post the values of checkboxes are set to NULL when I don't check then in order (1, 2, 3, etc).

我需要在没有为了选择其中任何(即4,5)。

I need to select any of them in no order (i.e. 4, 5).

MODEL:

public class AssignUsersViewModel
{
    [Display(Name = "Check to select")]
    public bool Select { get; set; }

    public int Id { get; set; }

    [Display(Name = "App. Username")]
    public string UserName { get; set; }

    [Required]
    public string GivenName { get; set; }

    [Required]
    public string Surname { get; set; }

    [Display(Name = "Roles")]
    public IList<Roles> Roles { get; set; }
}

public class AssignUsersAddModel
{
    public bool Select { get; set; }

    public int Id { get; set; }

    public IEnumerable<SelectedRoles> selectedRoles { get; set; }
}

public class SelectedRoles
{
    public string Name { get; set; }
}

CSHTML:

CSHTML:

@model IList<AspNetIdentity2DRH.Models.AssignUsersViewModel>
@using (Html.BeginForm("UsersAddToApp", "UsersAdmin", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    <table class="table">
        <tr>
            <th>Check for add</th>
            <th>Username</th>
            <th>Givenname</th>
            <th>Surename</th>
            <th>Roles</th>
        </tr>
        @for (int i = 0; i < Model.Count(); i++)
        {
            <tr>
                <td>
                    @Html.CheckBoxFor(x => x[i].Select)
                    @Html.HiddenFor(x => x[i].Id)
                </td>
                <td>
                    @Html.DisplayFor(x => x[i].UserName)
                </td>
                <td>
                    @Html.DisplayFor(x => x[i].GivenName)
                </td>
                <td>
                    @Html.DisplayFor(x => x[i].Surname)
                </td>
                <td>
                    <div class="row">
                        <div class="form-group">
                            @for (int j = 0; j < Model[i].Roles.Count(); j++)
                            { 
                                <div class="col-sm-4">
                                    <input type="checkbox" name="[@i.ToString()].selectedRoles[@j.ToString()].Name" value="@Model[i].Roles[j].Name" class="checkbox-inline" />
                                    @Html.Label(Model[i].Roles[j].Name, new { @class = "control-label", @data_toggle = "tooltip", @data_placement = "top", @data_original_title = Model[i].Roles[j].Description })
                                </div>
                            }
                        </div>
                    </div>
                </td>
            </tr>
        }
    </table>
    <p>
        <input type="submit" value="Add existing user" class="btn btn-primary" />
        <input type="button" value="Cancel" onclick="window.location.href = '@Url.Action("UsersIndex", "UsersAdmin")';" class="btn btn-cancel" />
    </p>
}

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UsersAddToApp(List<AssignUsersAddModel> model)
{
    if (ModelState.IsValid)
    {
        foreach (AssignUsersAddModel item in model)
        {
            if (item.Select)
            {
                using (DbContextTransaction dbtrans = db.Database.BeginTransaction())
                {
                    try
                    {
                        int appId = (int)Session["ApplicationId"];
                        Users user = UserManager.FindById(item.Id);
                        db.ApplicationUsers.Add(new ApplicationUsers { ApplicationId = appId, UserId = user.Id });
                        db.SaveChanges();
                        foreach (SelectedRoles RolesItem in item.selectedRoles)
                        {
                            int roleId = db.Roles.Where(r => r.Name == RolesItem.Name).Select(r => r.Id).FirstOrDefault();
                            db.UserApplicationRoles.Add(new UserApplicationRoles { ApplicationId = appId, UserId = user.Id, RoleId = roleId });
                            db.SaveChanges();
                        }
                        dbtrans.Commit();
                    }
                    catch (Exception)
                    {
                        dbtrans.Rollback();
                    }
                }

            }
        }
        return RedirectToAction("UsersAddToApp");
    }
    ModelState.AddModelError("", "An error has occurred. Contact system administrator.");
    return RedirectToAction("UsersAddToApp");
}

问题是,当我选择复选框(除了第一个,或最后o一个在中间,该行:

The problem is when I select checkboxes (all except the first, or the last o one in the middle, the line:

foreach (SelectedRoles RolesItem in item.selectedRoles)

发送item.selectedRoles为null。

Sends item.selectedRoles is null.

我怎么能做到这一点吗?

How I could do this right?

推荐答案

DefaultModelBinder 只会结合的集合,其中集合项的索引以零开始,是连续的。你的问题是你手动创建一个复选框元素。由于未选中复选框不回来后,如果你选中其中一个,那么它和任何后续复选框值当您提交将不会绑定到集合。

The DefaultModelBinder will only bind collections where the indexers of the collection items start at zero and are consecutive. You problem is that you are manually creating a checkbox element. Since unchecked checkboxes do not post back, if you uncheck one, then it and any subsequent checkbox values will not be bound to the collection when you submit.

接下来你去一个复选框绑定到字符串值。一个复选框有2个状态,旨在重新present一个布尔值。

Next your trying to bind a checkbox to a string value. A checkbox has 2 states and is designed to represent a boolean value.

您还没有表现出你角色(视图)模型,但它应该包括布尔属性,来指示,如果有被选中

You have not shown you Role (view) model but it should include a boolean property indicating if it has been selected

public class Role
{
  public int ID { get; set; }
  public string Name { get; set; }
  public bool IsSelected { get; set; }
}

然后在视图中,使用强类型HTML辅助方法让你获得正确的双向模型绑定

Then in the view, use strongly type html helpers so you get correct 2 way model binding

@for (int j = 0; j < Model[i].Roles.Count; j++)
{ 
  @Html.HiddenFor(m => m[i].Roles[j].Name) // or better use the ID property
  @Html.CheckBoxFor(m => m[i].Roles[j].IsSelected)
  @Html.LabelFor(m => m[i].Roles[j].IsSelected, Model[i].Roles[j].Name)
}

然后在POST方法,您的集合将被正确绑定,你可以使用访问选定的角色说,

Then in the POST method, your collection will be correctly bound and you could access the selected roles using say,

List<string> selectedRoles = model.Roles.Where(r => r.IsSelected);

请注意您可能还需要包括对 Role.ID (而该 Role.Name 属性),所以你并不需要在您的文章的方法执行数据库查找的foreach 循环。

Note you may also want to include a hidden input for the Role.ID (rather that the Role.Name property) so you do not need to perform database lookups in your POST methods foreach loop.

边注:您的帖子方法需要为

Side note: Your post method needs to be

public ActionResult UsersAddToApp(List<AssignUsersViewModel> model)

不是 ListAssignUsersAddModel&GT;模型

这篇关于POST到MVC控制器IEnumerable的嵌套型号为空时,我没有选择,为了复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆