@ Html.CheckboxFor也没有<input />将复选框值传回控制器(绑定问题)

时间:2015-08-06 01:48:17

标签: c# html asp.net-mvc razor

所以现在我正在尝试创建一个用户管理页面。该页面的主要模型实际上是一个IdentityUser,但我试图从视图中更新的模型是IdentityRole

以下是观点:

@model AG.SharedServices.DTO.IdentityUser

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>IdentityUser</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            <ul>
                @foreach (var role in TempData["Roles"] as IEnumerable<AG.SharedServices.DTO.IdentityRole>)
                {
                    <li>
                        <input name="@role.Name" type="checkbox" value="@role.Selected" />@role.Name
                    </li>
                }
            </ul>

        </div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

我也尝试将“<input type="submit" value="Save" class="btn btn-default" />”替换为“@Html.CheckBoxFor(r => role.Selected)”但是两个都没有传回复选框的值,它总是返回false。并且CheckBoxFor不会接受任何其他值而不是IdentityUser,这是一个问题,如果我知道如何让它接受不同的模型它会有所帮助

这是控制器。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using AG.SharedServices.DTO;
using System.Data;
using AG.BusinessServices;
using System.Net;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;

namespace AG.AGWeb.Controllers
{
    public class UserAdminController : Controller
    {
        private ApplicationUserManager _userManager;

        public UserAdminController()
        {

        }

        public UserAdminController(ApplicationUserManager userManager)
        {
            _userManager = userManager;
        }

        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }
        // GET: UserAdmin
        public ActionResult Index()
        {
            var users = UserManager.Users;
            return View(users);
        }

        // GET: UserAdmin/Details/5
        public ActionResult Details(int id)
        {
            return View();
        }

        // GET: UserAdmin/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: UserAdmin/Create
        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                // TODO: Add insert logic here

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // GET: UserAdmin/Edit/5
        public ActionResult Edit(string id)
        {
            var user = UserManager.FindById(id);
            var roleService = new RoleService();
            var roles = roleService.GetRoles();
            //add code to check users roles
            var userRoles = UserManager.GetRoles(id);
            foreach(var role in roles)
            {
                role.Selected = userRoles.Contains(role.Name);
            }
            TempData["Roles"] = roles;
            TempData.Keep("Roles");
            return View(user);
        }

        // POST: UserAdmin/Edit/5
        [HttpPost, ActionName("Edit")]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit(IdentityUser model, string id)
        {
            try
            {
                // TODO: Add update logic here
                if (model == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
                if (ModelState.IsValid)
                {
                    var user = UserManager.FindById(id);
                    user.FirstName = model.FirstName;
                    user.LastName = model.LastName;
                    user.PhoneNumber = model.PhoneNumber;
                    var results = await UserManager.UpdateAsync(user);
                    if (results.Succeeded)
                    {
                        var roles = TempData["Roles"] as IEnumerable<IdentityRole>;
                        foreach(var role in roles)
                        {
                            if (role.Selected && await UserManager.IsInRoleAsync(id, role.Id) == false)
                            {
                                await UserManager.AddToRoleAsync(id, role.Id);
                            }
                            else
                            {
                                await UserManager.RemoveFromRoleAsync(id, role.Id);
                            }
                        }
                    }

                }

                    return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // GET: UserAdmin/Delete/5
        public ActionResult Delete(string id)
        {
            var user = UserManager.FindById(id);
            return View(user);
        }

        // POST: UserAdmin/Delete/5
        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                // TODO: Add delete logic here

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
}

我们试图传递的模型是IdentityRole,如下所示:

using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AG.SharedServices.DTO
{
    public class IdentityRole : IRole
    {
        /// <summary>
        /// Default constructor for Role 
        /// </summary>
        public IdentityRole()
        {
            Id = Guid.NewGuid().ToString();
        }
        /// <summary>
        /// Constructor that takes names as argument 
        /// </summary>
        /// <param name="name"></param>
        public IdentityRole(string name)
            : this()
        {
            Name = name;
        }

        public IdentityRole(string name, string id)
        {
            Name = name;
            Id = id;
        }

        /// <summary>
        /// Role ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// Role name
        /// </summary>
        public string Name { get; set; }

        public bool Selected { get; set; }
    }
}

有没有人对如何在视图中使用foreach循环以传递IdentityRoles并更改角色的Selected值以便将用户分配给角色有任何想法?

谢谢!

1 个答案:

答案 0 :(得分:1)

你应该在你的行动中使用类似于角色数组的UserIdentityModel

public class UserIdentityModel
{
   ...

   public IList<IdentityRole> Roles { get; set; }
}

并在视图

上创建角色列表
   @model UserIdentityModel
   ...
   <ul>
       @for (var i = 0; i < Model.Roles.Count; i++)
       {
          <li>
             <input name="@("Roles[" + i + "].Selected")" type="checkbox" value="@(Model.Roles[i].Selected)" />@Model.Roles[i].Name
             <input type="hidden" name="@("Roles[" + i + "].Name")" value="@(Model.Roles[i].Name)">
             <input type="hidden" name="@("Roles[" + i + "].Id")" value="@(Model.Roles[i].Id)">
          </li>
       }
    </ul>

在您的帖子操作中,您将收到带有角色集合的UserIdentityModel

public ActionResult Edit(string id)
{
   var user = UserManager.FindById(id);
   var model = new UserIdentityModel();
   ///Fill all fields of the model      
   return View(model);
}

// POST: UserAdmin/Edit/5
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(UserIdentityModel model)
{
   ...
   foreach(var role in model.Roles)
   {
      ...
   }