Как я могу отобразить список ролей в представлении Razor Pages?

2

Я пытаюсь добавить список ролей в моем основном веб-приложении asp.net на страницу Razor, но я не уверен, как это сделать. Я хочу, чтобы пользователь мог выбирать, какую роль должен регистрировать новый пользователь.

Сама модель ввода выглядит так:

public class InputModel
    {

        [Required]
        [DataType(DataType.Text)]
        [Display(Name = "Full name")]
        public string Name { get; set; }

        [Required]
        [Display(Name = "Payroll")]
        [DataType(DataType.Text)]
        public string Payroll { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Required]
        public List<String> Roles { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [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; }
    }

Как ниже, в настоящее время у меня есть жестко заданные значения на моем представлении (выдержка):

<div class="form-group">
            <label asp-for="Input.Roles"></label>
            <select asp-for="Input.Roles" class="form-control">
                <option value="Administrator">Administrator</option>
                <option value="NormalUser" selected>NormalUser</option>
            </select>
        </div>

Это работает для того, что я хочу, но я хотел бы заменить это динамическим списком ролей из моего приложения.

В моем методе OnGet() есть следующее:

var roles = _roleManager.Roles.Select(x => x.Name).ToList();
InputModel vm = new InputModel();
vm.Roles = roles;
ReturnUrl = returnUrl;

Я спрашиваю, как получить список ролей в форме, которую я могу использовать на самой странице.

Благодарю.

редактировать... полный код позади:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using MailTracker.Models;

namespace MailTracker.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterModel : PageModel
{
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<IdentityRole> _roleManager;
    private readonly ILogger<RegisterModel> _logger;
    private readonly IEmailSender _emailSender;

    public RegisterModel(
        UserManager<ApplicationUser> userManager,
        RoleManager<IdentityRole> roleManager,
        SignInManager<ApplicationUser> signInManager,
        ILogger<RegisterModel> logger,
        IEmailSender emailSender)
    {
        _userManager = userManager;
        _roleManager = roleManager;
        _signInManager = signInManager;
        _logger = logger;
        _emailSender = emailSender;
    }

    [BindProperty]
    public InputModel Input { get; set; }

    public string ReturnUrl { get; set; }

    public class InputModel
    {

        [Required]
        [DataType(DataType.Text)]
        [Display(Name = "Full name")]
        public string Name { get; set; }

        [Required]
        [Display(Name = "Payroll")]
        [DataType(DataType.Text)]
        public string Payroll { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Required]
        public List<SelectListItem> RoleList { get; set; }

        public string SelectedRole { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [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 void OnGet(string returnUrl = null)
    {
        var roles = _roleManager.Roles.Select(x => x.Name).ToList();
        InputModel vm = new InputModel
        {
            RoleList = roles.Select(x => new SelectListItem { Text = x, Value = x }).ToList()
        };
        ReturnUrl = returnUrl;
    }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser {
                UserName = Input.Email,
                Email = Input.Email,
                Name = Input.Name,
                Payroll = Input.Payroll
            };

            string role = Input.SelectedRole;

            var result = await _userManager.CreateAsync(user, Input.Password);
            if (result.Succeeded)
            {
                _logger.LogInformation("User created a new account with password.");

                //add default NormalUser role to user




                await _userManager.AddToRoleAsync(user, role);

                //

                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { userId = user.Id, code = code },
                    protocol: Request.Scheme);

                await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                    $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        // If we got this far, something failed, redisplay form
        return Page();
    }
}

}

и самой полной страницы:

@page
@model RegisterModel
@{
    ViewData["Title"] = "Register";
}

<h2>@ViewData["Title"]</h2>

<div class="row">
    <div class="col-md-4">
        <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
            <h4>Create a new account.</h4>
            <hr />

            <div class="form-group">
                <label asp-for="Input.Name"></label>
                <input asp-for="Input.Name" class="form-control" />
                <span asp-validation-for="Input.Name" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Input.Payroll"></label>
                <input asp-for="Input.Payroll" class="form-control" />
                <span asp-validation-for="Input.Payroll" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Input.RoleList"></label>
                <select asp-for="Input.SelectedRole" asp-items="Model.Input.RoleList" class="form-control"></select>
            </div>

            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Input.Email"></label>
                <input asp-for="Input.Email" class="form-control" />
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Input.Password"></label>
                <input asp-for="Input.Password" class="form-control" />
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.ConfirmPassword"></label>
                <input asp-for="Input.ConfirmPassword" class="form-control" />
                <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
            </div>
            <button type="submit" class="btn btn-default">Register</button>
        </form>
    </div>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}
Теги:
razor-pages

2 ответа

2
Лучший ответ

Вы можете выполнить эти шаги, чтобы загрузить список в <select> tag helper:

1) Создайте свойство List<SelectListItem> в viewmodel (например, InputModel) и свойство string чтобы сохранить выбранное значение.

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

public List<SelectListItem> RoleList { get; set; }

2) Преобразование существующего свойства List<string> с помощью LINQ Select объект List<SelectListItem> и назначьте его свойству RoleList.

vm.RoleList = vm.Roles.Select(x => new SelectListItem { Text = x, Value = x }).ToList();

3) Наконец, используйте помощник тега asp-items для привязки его к элементу <select>:

<select asp-for="Input.SelectedRole" asp-items="Input.RoleList" class="form-control"></select>

Обновить:

В качестве альтернативы вы можете добавить List<SelectListItem> в качестве свойства PageModel с членами-выражениями:

public List<SelectListItem> RoleList => vm.Roles.Select(x => new SelectListItem { Text = x, Value = x }).ToList();

И установите Model.RoleList для Model.RoleList asp-items:

<select asp-for="Input.SelectedRole" asp-items="Model.RoleList" class="form-control"></select>

Если вы не хотите добавлять свойство List<SelectListItem>, вы можете использовать ViewData назначенный с помощью списка опций:

ViewData["RoleList"] = vm.Roles.Select(x => new SelectListItem { Text = x, Value = x }).ToList();

И привязывайтесь к странице следующим образом:

<select asp-for="Input.SelectedRole" asp-items="@((List<SelectListItem>)ViewData["RoleList"])"></select>

Тег <option> будет создан автоматически, больше не нужно его жестко кодировать.

Примечание. Избегайте привязки List<string> непосредственно к атрибуту asp-for, поскольку для asp-for для <select> предназначенного для одиночного значения (т.е. Выбранного значения из списка <option>), также вы должны удалить свойство RequiredAttribute for Roles в качестве атрибут теперь не нужен и может вызвать ошибку проверки модели.

Дополнительная ссылка: помощник Select Tag

  • 0
    спасибо за возвращение: <select asp-for = "SelectedRole" asp-items = "Model.RoleList" class = "form-control"> </ select> показывает ошибку на странице. RegisterModel не содержит определения для RoleList. Боюсь, я не включил достаточно информации. Я отредактировал свой оригинальный пост, чтобы показать полный код. Можете ли вы посоветовать, пожалуйста?
  • 0
    Я отредактировал часть <select> в соответствии с вашими требованиями, а также удалил атрибут [Required] над свойством Roles .
Показать ещё 4 комментария
1

Сделайте это следующим образом: <select asp-for="Role" asp-items="Model.RolesItems"></select>

public List<SelectListItem> RolesItems 
public string Role

Подробнее здесь

Ещё вопросы

Сообщество Overcoder
Наверх
Меню