Исключение ArgumentNullException: Значение не может быть равно нулю. (Параметр «предметы») Форма регистрации с использованием удостоверения с Ролевой авторизацией

#asp.net #asp.net-mvc #asp.net-core

Вопрос:

Я только начинаю ASP.NET 5 Основных MVC. Я использовал удостоверение личности для регистрации. Когда я отправляю форму регистрации, Model.isValid возвращает false в сообщении на странице razor. Единственное, что публикуется, — это выпадающий список, все остальные-пустые. Если я удалю выпадающий список ролей из реестра, а затем отправлю его, он будет работать нормально.(Ввод.Имя-это роль)

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

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

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

    public string ReturnUrl { get; set; }

    public IList<AuthenticationScheme> ExternalLogins { get; set; }

    public class InputModel
    {
        [Required]
        [DataType(DataType.Text)]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }

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

        [Required]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { 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 string Name { get; set; }
    }

    //public void OnGet(string returnUrl = null)
    //{
    //    ViewData["roles"] = _roleManager.Roles.ToList();
    //    ReturnUrl = returnUrl;
    //}

    public async Task OnGetAsync(string returnUrl = null)
    {
        ViewData["roles"] = _roleManager.Roles.ToList();
        ReturnUrl = returnUrl;
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
    }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
        var role = _roleManager.FindByIdAsync(Input.Name).Resu<
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email, FirstName = Input.FirstName, LastName = Input.LastName };
            var result = await _userManager.CreateAsync(user, Input.Password);
            if (result.Succeeded)
            {
                _logger.LogInformation("User created a new account with password.");
                await _userManager.AddToRoleAsync(user, role.Name);

                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
                    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>.");

                if (_userManager.Options.SignIn.RequireConfirmedAccount)
                {
                    return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
                }
                else
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);
                    return LocalRedirect(returnUrl);
                }
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
            ViewData["roles"] = _roleManager.Roles.ToList();
        }

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

}
Снимок экрана отладки

Приведенный ниже код является элементом выбора

 @page
@model RegisterModel
@{
ViewData["Title"] = "Register";
var roles = (List<IdentityRole>)ViewData["roles"];
}

<div class="container">
 <div style="padding-top:80px;"></div>
 <div class="container pt-5 pb-3" style="background-color: white; 
 width:500px; height:auto; border-radius:10px;">
    <div class="text-center">
        <h3>Softcode Gem Solution</h3>
        <h6><img src="~/images/icons/add_user_male_32px.png" alt="Register" />Register with your Credentials</h6>
    </div>
    <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
        @Html.AntiForgeryToken()
        <div class="form-floating mb-3 ">
            <input asp-for="Input.FirstName" type="text" class="form-control" id="firstname" name="firstname" placeholder="First Name" style="border-radius: 5px; ">
            <label asp-for="Input.FirstName"><img src="~/images/icons/name_24px.png" />First Name</label>
            <span asp-validation-for="Input.FirstName" class="text-danger"></span>
        </div>
        <div class="form-floating mb-3">
            <input asp-for="Input.LastName" type="text" class="form-control" id="lastname" name="lastname" placeholder="Last Name" style="border-radius: 5px; ">
            <label asp-for="Input.LastName"><img src="~/images/icons/name_24px.png" />Last Name</label>
            <span asp-validation-for="Input.LastName" class="text-danger"></span>
        </div>
        <div class="form-floating mb-3">
            <input asp-for="Input.Email" type="email" class="form-control" id="email" name="email" placeholder="Email" style="border-radius: 5px; ">
            <label asp-for="Input.Email"><img src="~/images/icons/email_24px.png" />Email address</label>
            <span asp-validation-for="Input.Email" class="text-danger"></span>
        </div>
        <div class="form-floating mb-3 pb-2">
            <input asp-for="Input.Password" type="password" class="form-control" id="password" name="password" placeholder="Password" style="border-radius: 5px;">
            <label asp-for="Input.Password"><img src="~/images/icons/password_24px.png" />Password</label>
            <span asp-validation-for="Input.Password" class="text-danger"></span>
        </div>
        <div class="form-floating mb-3 pb-2">
            <input asp-for="Input.ConfirmPassword" type="password" class="form-control" id="confirmpassword" name="confirmpassword" placeholder="Confirm Password" style="border-radius: 5px;">
            <label asp-for="Input.ConfirmPassword"><img src="~/images/icons/password_24px.png" />Confirm Password</label>
            <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
        </div>
        <div class="form-control mb-3 pb-2">
            <label asp-for="Input.Name"></label>
            <select asp-for="Input.Name" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
            <span asp-validation-for="Input.Name" class="text-danger"></span>
        </div>
        <button class="w-100 btn btn-lg btn-primary " type="submit">Register</button>
        <a asp-page="./Login" asp-route-returnUrl="@Model.ReturnUrl" style="text-decoration:none;"><p class="mt-3 mb-2 text-muted ">Already Registered? Login</p></a>
    </form>
</div>
 
 @section Scripts {
<partial name="_ValidationScriptsPartial" />
}
 

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

Комментарии:

1. Несмотря на то, что вы можете добавить роли в форму регистрации, чтобы изучить структуру, концептуально роли (следовательно, раскрывающийся список ролей) не должны быть в форме регистрации, поскольку роли должны назначаться и управляться администраторами, а не пользователями во время регистрации.

2. @Dush Хорошо, спасибо за совет. Итак, есть ли способ сохранить пользователей неактивными, например, до тех пор, пока администратор не назначит роль?

Ответ №1:

В вашем коде это выглядит так, как будто существует конфликт Name , как в вашем Register.chtml

Сначала измените public string Name { get; set; } код в поле RegisterModel на

 [Display(Name = "User Role")] 
public string UserRole { get; set; }
 

Затем посмотрите на эту часть вашего кода input.Name и имя в SelectList :

 <div class="form-control mb-3 pb-2">
     <label asp-for="Input.Name"></label>
     <select asp-for="Input.Name" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
     <span asp-validation-for="Input.Name" class="text-danger"></span>
 </div>
 

Просто попробуйте переключиться на это:

 <div class="form-control mb-3 pb-2">
     <label asp-for="Input.UserRole"></label>
     <select asp-for="Input.UserRole" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
     <span asp-validation-for="Input.UserRole" class="text-danger"></span>
</div>
 

`

Комментарии:

1. Большое спасибо, что это сработало, я назначил поле имени, также похожее на идентификатор, для каждого поля ввода, поэтому оно не публиковалось с данными, в этом тоже была проблема

Ответ №2:

исправьте действие на GetAsync, добавьте роли

 ....
 ViewBag.Roles = _roleManager.Roles.Select (i=> new SelectListItem {
    Value= i.Id.ToString(),
    Text= i.Name
   }).ToList();
....

 

и посмотреть

  <select asp-for="Input.Name" class="form-control" asp-items="@ViewBag.Roles"></select>
 

И я не вижу вашего ввода, но что-то подсказывает мне, что вместо ввода.Имя, которое вы должны использовать для ввода.Идентификатор или создайте его.

Комментарии:

1. Его Input.Name, где я должен его изменить? В модели?

2. @Umar Можете ли вы опубликовать весь код за страницей razor

3. Это register.cshtml или register.cshtml.cs(часть C#)?

4. Невозможно использовать ViewBag в register.cshtml.cs