如何将模型中的对象列表传递回控制器?

时间:2014-01-30 21:08:54

标签: asp.net-mvc razor

更新:解决方案是使用EditorTemplate。请参阅以下解决方案:

我想将模型传递给控制器​​/从控制器传递模型,让我设置名称,并将值设置为未确定的角色(作为复选框)。当我检查回发时,我在模型中获取Name的值,但是Roles为null。如何判断选中了哪些复选框?

型号:

public class MyModel
{
    public string Name { get; set; }
    public IEnumerable<RoleItem> Roles { get; set; }
}

public class RoleItem
{
    public String Name { get; set; }
    public String Id { get; set; }
    public bool Selected { get; set; }
    public RoleItem(String id, String name, bool selected = false)
    {
        this.Name = name;
        this.Id = id;
        this.Selected = selected;
    }
}

剃刀:

@model WebApplication1.Controllers.MyModel

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    @Html.TextBoxFor(m=>m.Name)

    foreach (var m in Model.Roles)
    {
        <div>
            @Html.Label(m.Id, m.Name)
            @Html.CheckBox(m.Id, m.Selected, new { id = @m.Id })
        </div>
    }
    <input type="submit"/>
}

1 个答案:

答案 0 :(得分:0)

目标:允许任何管理员将新用户添加到Asp身份表,并使用复选框为他们分配在列表中定义的角色。

型号:

public class RegisterViewModel
{
    [Display(Name = "Name")]
    public string FullName { get; set; }

    [Required]
    [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 List<RoleItem> Roles { get; set; }

}

public class RoleItem
{
    public String Name { get; set; }
    public String Id { get; set; }
    public bool IsMember { get; set; }
}

Controller(GET):它读取数据库中的所有角色,并将它们转换为RoleItems列表。这会将字符“r”添加到id字段之前,因为某些浏览器的id存在以数字开头的问题。我们希望确保默认情况下选中“Users”组,因此我们在列表中找到此值并将IsMember属性设置为true。我们检查请求以查看页面是否从成功的POST(见下文)

重定向到此处
    // GET: /Account/AddUser
    [Authorize(Roles = "Administrators")]
    public ActionResult AddUser()
    {
        var rolesDb = new ApplicationDbContext();  //Users, Administrators, Developers, etc
        ViewBag.AddSuccess = Request["added"]=="1" ? true : false;

        var roleItems = rolesDb.Roles.Select(r => new RoleItem() { Id = "r" + r.Id, Name = r.Name, IsMember = false }).ToList(); //add an r to get around a browser bug
        var users = roleItems.FirstOrDefault(r => r.Name == "Users");  //Get the row that has the Users value and set IsMember=true
        if (users != null) 
            users.IsMember = true;
        var m = new RegisterViewModel() {Roles = roleItems};
        return View(m);
    }

观点:非常标准的东西。注意底部的 @ Html.EditorFor(x =&gt; x.Roles),它使用编辑器模板(如下)

@model cherry.Models.RegisterViewModel
@{
    ViewBag.Title = "AddUser";
}

<h2>@ViewBag.Title.</h2>

@if (Convert.ToBoolean(ViewBag.AddSuccess))
{
    <text>User added!</text>
}

@using (Html.BeginForm("AddUser", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.LabelFor(m => m.EmailAddress, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.EmailAddress, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.FullName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.FullName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { value = Model.Password, @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new {@class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new {value = Model.ConfirmPassword,  @class = "form-control" }) 
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>

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

}

EditorTemplate:

必须为模板指定与您为其创建模板的对象相同的名称。您还必须将此对象放在您正在为其设计的视图下方的名为 EditorTemplates 的文件夹中,或者您可以将该文件夹放在共享文件夹中。

Views \ Account \ EditorTemplates \ RoleItem.cshtml

@model cherry.Models.RoleItem
<div>
    @Html.CheckBoxFor(x => x.IsMember)
    @Html.LabelFor(x => x.IsMember, Model.Name)
    @Html.HiddenFor(x => x.Name)
</div>