I am trying to move the register page that was scaffolded by ASP.net core to a controller so I can have a better control on the way I open it and for organisation reasons. Where the view was previously in
我正试图将ASP.net核心搭建的注册页面移到一个控制器上,这样我就可以更好地控制打开它的方式和组织原因。视图以前所在的位置
Areas
区域
- Identity
-- Pages
--- Account
now, I want it to be at
现在,我希望它在
Views
-Account
视图-帐户
And I want to open this view using an AccountController.
我想使用AccountController打开这个视图。
I tried opening it; starting the model; calling some methods, just like this:
我试着打开它;启动模型;调用一些方法,如下所示:
[HttpGet]
public async Task<IActionResult> RegisterAsync()
{
var model = new RegisterModel(_userManager, _userStore, _signInManager, _logger, _emailSender);
model.OnGetAsync("Home/Index").Wait() ;
return View("Register", model);
}
Everytime I call the action on the controller, I get an exception in the View itself that the model is null.
每次我在控制器上调用操作时,我都会在视图本身中得到一个异常,即模型为null。
What should I do?
我该怎么办?
更多回答
Do u want to move the registration functionality to a controller and customize it?
是否要将注册功能移动到控制器并进行自定义?
@YasinARLI yes. Exactly
@YasinARLI是的。确切地
优秀答案推荐
When you try with MVC ,the services shouldn't be required for your viewmodel ,also, you have to move the codes inside your Razor Page Handlers into ccontroller,don't call the handler directly(model.OnGetAsync("Home/Index")
),a minial example here:
当你尝试MVC时,你的视图模型不应该需要这些服务,而且,你必须将Razor页面处理程序中的代码移动到ccontroller中,不要直接调用处理程序(model.OnGetAsync(“Home/Index”)),这里是一个小示例:
Models:
型号:
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; }
}
View:
视图:
@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" />
}
Controller:
控制器:
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;
}
}
Result:
结果:
更多回答
我是一名优秀的程序员,十分优秀!