Я разрабатываю приложение Razor, и мне нужен администратор для назначения или обновления ролей пользователей. Я использую флажок для выполнения этого действия. До сих пор мне удавалось заполнить представление, чтобы показать пользователей и их соответствующие роли, отмеченные флажком, но я не смог обновить их роли, так как всякий раз, когда флажок для добавления роли установлен, он не t добавить роль пользователю. Думаю, виновата эта строка: var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
.
Это Модель:
public class ManageUserRolesViewModel
{
public string RoleId { get; set; }
public string RoleName { get; set; }
public bool Selected { get; set; }
}
Это страница:
<form method = "post">
<div class = "card">
<div class = "card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class = "card-body">
@foreach (var x in Model.UserRoles)
{
<div class = "form-check m-1">
<input type = "hidden" asp-for = "@x.RoleId" />
<input type = "hidden" asp-for = "@x.RoleName" />
<input asp-for = "@x.Selected" class = "form-check-input" />
<label class = "form-check-label" asp-for = "@x.Selected">
@x.RoleName
</label>
</div>
}
<div asp-validation-summary = "All" class = "text-danger"></div>
</div>
<div class = "card-footer">
<input type = "submit" value = "Update" class = "btn btn-primary" style = "width:auto" />
<a asp-page = "/Account/UserManagement/UserList" class = "btn btn-primary" style = "width:auto">Cancel</a>
</div>
</div>
</form>
Это модель страницы:
public class ManageModel : PageModel
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly BankAssesmentApplicationIdentityDbContext _db;
private readonly UserManager<IdentityUser> _userManager;
public ManageModel(
RoleManager<IdentityRole> roleManager,
UserManager<IdentityUser> userManager,
BankAssesmentApplicationIdentityDbContext db)
{
_db = db;
_userManager = userManager;
_roleManager = roleManager;
}
public IList<ManageUserRolesViewModel> UserRoles = new List<ManageUserRolesViewModel>();
public string UserID { get; set; }
public async Task<IActionResult> OnPostAsync(List<ManageUserRolesViewModel> model, string userId)
{
UserID = userId;
if (ModelState.IsValid)
{
IdentityUser user = await _userManager.FindByNameAsync(userId);
if (user == null)
{
return Page();
}
var roles = await _userManager.GetRolesAsync(user);
var result = await _userManager.RemoveFromRolesAsync(user, roles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot remove user existing roles");
return Page();
}
var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
await _userManager.AddToRolesAsync(user, selectedRoles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot add selected roles to user");
return Page();
}
return RedirectToPage("/Account/UserManagement/UserList");
}
return Page();
}
public async Task<IActionResult> OnGetAsync(string userId)
{
UserID = userId;
var user = await _userManager.FindByEmailAsync(userId);
if (user == null)
{
return Page();
}
var model = new List<ManageUserRolesViewModel>();
foreach (var role in _roleManager.Roles.ToList())
{
ManageUserRolesViewModel roles = new ManageUserRolesViewModel
{
RoleId = role.Id,
RoleName = role.Name,
};
UserRoles.Add(roles);
if (await _userManager.IsInRoleAsync(user, role.Name))
{
roles.Selected = true;
}
else
{
roles.Selected = false;
}
model.Add(roles);
}
return Page();
}
}
@coder_b Он говорит, что количество = 0
хм.. надеюсь, это поможет решить проблему stackoverflow.com/questions/62783005/…
@coder_b Спасибо, чувак, но это не особо помогает.
@ user: 3843256 взгляните на этот образец, он работает нормально, единственная разница в том, что вы используете для каждого, что означает, что привязка не выполняется, измените привязку индекса на основе счетчика.
Я только что запустил вашу скрипку, RoleName выдает нулевое значение
на самом деле это не имеет значения, так как я был привязан к ярлыку, он не публикуется, я надеюсь, что никто не собирается менять имя роли, не так ли? вы после выбранного поля, чтобы обновить свой объект использования
Во-первых, вам нужно знать, что для каждого свойства сложного типа привязка модели просматривает источники для шаблона имени prefix.property_name
. Если ничего не найдено, он ищет просто property_name
без префикса. Ваш бэкэнд хочет получить модель списка, поэтому то, что вы передаете, должно быть [index].PropertyName
. Но то, что вы сделали, приведет к серверным входам с тем же именем, система привязки модели может не соответствует значению списка.
Тогда вам нужно знать, что asp-for = "@x.Selected"
сгенерирует значение для флажка, но не изменит значение при изменении состояния флажка, вам нужно создать событие щелчка, чтобы изменить значение:
<input asp-for = "@x.Selected" onclick = "$(this).val(this.checked ? true : false)"/>
Что вам нужно изменить, как показано ниже:
<form method = "post">
<div class = "card">
<div class = "card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class = "card-body">
@*Begin change*@
@{ int i = 0;}
@foreach (var x in Model.UserRoles)
{
<div class = "form-check m-1">
<input type = "hidden" asp-for = "@x.RoleId" name = "[@i].RoleId"/>
<input type = "hidden" asp-for = "@x.RoleName" name = "[@i].RoleName"/>
<input asp-for = "@x.Selected" name = "[@i].Selected" class = "form-check-input" onclick = "$(this).val(this.checked ? true : false)"/>
<label class = "form-check-label" asp-for = "@x.Selected">
@x.RoleName
</label>
</div>
i++;
}
@*End change*@
<div asp-validation-summary = "All" class = "text-danger"></div>
</div>
<div class = "card-footer">
<input type = "submit" value = "Update" class = "btn btn-primary" style = "width:auto" />
<a asp-page = "/Account/UserManagement/UserList" class = "btn btn-primary" style = "width:auto">Cancel</a>
</div>
</div>
</form>
Результат:
что вы получите selectedRoles.ToList().Count, если попробуете из режима отладки?