【发布时间】:2015-08-06 15:32:13
【问题描述】:
所以现在我正在尝试创建一个用户管理页面。页面的主要模型实际上是一个 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>
我也试过用“@Html.CheckBoxFor(r => role.Selected)”替换“<input type="submit" value="Save" class="btn btn-default" />”,但都没有传回复选框的值,它总是返回 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 值以便将用户分配给角色?
谢谢!
【问题讨论】:
-
您没有在视图中的任何地方使用
CheckBoxFor()(查看您的问题标题)。您只需创建一个名称与您的模型完全没有关系的复选框集合,因此它们永远不会绑定到任何东西。使用代表您需要编辑的视图模型。 -
查看最近的编辑,我添加了我们尝试与
CheckBoxFor()一起使用的代码 -
没什么区别 - 您不会生成与您的模型相关的输入。而且在任何情况下,您都不能使用
foreach循环(它必须是for循环)
标签: c# html asp.net-mvc razor