如何将Account脚手架移至Controller?

问题描述 投票:0回答:1

我正在尝试将 ASP.net core 搭建的注册页面移至控制器,以便我可以更好地控制打开它的方式以及出于组织原因。视图之前所在的位置

地区

  • 身份 -- 页面 --- 账户

现在,我希望它位于

浏览量 -账户

我想使用 AccountController 打开此视图。

我尝试打开它;启动模型;调用一些方法,就像这样:

[HttpGet]
public async Task<IActionResult> RegisterAsync()
{
    var model = new RegisterModel(_userManager, _userStore, _signInManager, _logger, _emailSender);
    model.OnGetAsync("Home/Index").Wait() ;
    return View("Register", model);
}

每次我在控制器上调用操作时,我都会在视图本身中收到一个异常,即模型为空。

我该怎么办?

c# asp.net-mvc asp.net-core asp.net-mvc-scaffolding
1个回答
0
投票

当您尝试使用 MVC 时,您的视图模型不需要这些服务,这里是一个小示例:

型号:

public class InputModel
    {
        
        [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 class RegisterViewModel
    {
        public InputModel Input { get; set; } = default!;


        public string? ReturnUrl { get; set; }

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

查看:

@model RegisterViewModel

<div class="row">
    <div class="col-md-4">
        <form id="registerForm" asp-route-returnUrl="@Model?.ReturnUrl" method="post">
            <h2>Create a new account.</h2>
            <hr />
            <div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
            <div class="form-floating mb-3">
                <input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="[email protected]" />
                <label asp-for="Input.Email">Email</label>
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>
            <div class="form-floating mb-3">
                <input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
                <label asp-for="Input.Password">Password</label>
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
            <div class="form-floating mb-3">
                <input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
                <label asp-for="Input.ConfirmPassword">Confirm Password</label>
                <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
            </div>
            <button id="registerSubmit" type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
        </form>
    </div>
    <div class="col-md-6 col-md-offset-2">
        <section>
            <h3>Use another service to register.</h3>
            <hr />
            @{
                if ((Model?.ExternalLogins?.Count ?? 0) == 0)
                {
                    <div>
                        <p>
                            There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">
                                article
                                about setting up this ASP.NET application to support logging in via external services
                            </a>.
                        </p>
                    </div>
                }
                else
                {
                    <form id="external-account" asp-action="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
                        <div>
                            <p>
                                @foreach (var provider in Model.ExternalLogins!)
                                {
                                    <button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
                                }
                            </p>
                        </div>
                    </form>
                }
            }
        </section>
    </div>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

控制器:

public class AccountController : Controller
    {
        private readonly SignInManager<AppUser> _signInManager;
        private readonly UserManager<AppUser> _userManager;
        private readonly IUserStore<AppUser> _userStore;
        private readonly IUserEmailStore<AppUser> _emailStore;       
        private readonly IEmailSender _emailSender;
        public  AccountController
            (
            UserManager<AppUser> userManager,
            IUserStore<AppUser> userStore,
            SignInManager<AppUser> signInManager,            
            IEmailSender emailSender
            ) 
        {
            _userManager = userManager;
            _userStore = userStore;
            _emailStore = GetEmailStore();
            _signInManager = signInManager;
            
            _emailSender = emailSender;
        }
        [HttpGet]
        public async Task<IActionResult> Register(string returnUrl = null)
        {
            var registermodel = new RegisterViewModel {
                ReturnUrl = returnUrl,
                ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
            };
            return View(registermodel);
        }
        [HttpPost]
        public async Task<IActionResult> Register(RegisterViewModel registerViewModel)
        {
            registerViewModel.ReturnUrl ??= Url.Content("~/");
            registerViewModel.ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
            if (ModelState.IsValid)
            {
                var user = CreateUser();

                await _userStore.SetUserNameAsync(user, registerViewModel.Input.Email, CancellationToken.None);
                await _emailStore.SetEmailAsync(user, registerViewModel.Input.Email, CancellationToken.None);
                var result = await _userManager.CreateAsync(user, registerViewModel.Input.Password);

                if (result.Succeeded)
                {
                    

                    var userId = await _userManager.GetUserIdAsync(user);
                    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 = userId, code = code, returnUrl = registerViewModel.ReturnUrl },
                        protocol: Request.Scheme);

                    await _emailSender.SendEmailAsync(registerViewModel.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 RedirectToAction("RegisterConfirmation", new { email = registerViewModel.Input.Email, returnUrl = registerViewModel.ReturnUrl });
                    }
                    else
                    {
                        await _signInManager.SignInAsync(user, isPersistent: false);
                        return LocalRedirect(registerViewModel.ReturnUrl);
                    }
                }
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            return View(registerViewModel);
        }

        public IActionResult RegisterConfirmation()
        {
            //migrate from razor page to MVC yourself
            return Ok("Ok");
        }


        private AppUser CreateUser()
        {
            try
            {
                return Activator.CreateInstance<AppUser>();
            }
            catch
            {
                throw new InvalidOperationException($"Can't create an instance of '{nameof(AppUser)}'. " +
                    $"Ensure that '{nameof(AppUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
                    $"override the register page in /Areas/Identity/Pages/Account/Register.cshtml");
            }
        }

        private IUserEmailStore<AppUser> GetEmailStore()
        {
            if (!_userManager.SupportsUserEmail)
            {
                throw new NotSupportedException("The default UI requires a user store with email support.");
            }
            return (IUserEmailStore<AppUser>)_userStore;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.