我有一个简单的登录表单,其中包含一个输入字段,如:
<form asp-action="SendLoginEmail" method="post">
<div class="row">
<input asp-for="EmailAddress" placeholder="Adresse mail" class="form-control"/>
<div class="row">
<span asp-validation-for="EmailAddress"></span>
@if (Model != null && !string.IsNullOrWhiteSpace(Model.ErrorMessage))
{
<span class="field-validation-error">@Model.ErrorMessage</span>
}
</div>
</div>
<div class="row">
<button type="submit" id="login-button" class="challenge-action-item green-action-button link-button">Continuer</button>
</div>
</form>
这是控制器:
[HttpGet("login")]
[AllowAnonymous]
public IActionResult LoginGet(LoginModel model)
{
return View(model);
}
[HttpPost("login")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LoginPost(LoginModel model)
{
if (!ModelState.IsValid)
{
return View("Login", model);
}
...
}
[HttpPost("login")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Whatever(LoginModel model)
{
var error = "The one time login link has expired";
return RedirectToAction("Login", new LoginModel() {ErrorMessage = error});
}
除了验证错误之外,我还从模型填充ErrorMessage,让用户知道服务器端的潜在错误(电子邮件地址无法识别,一次登录链接已过期(从重定向)等... )
因此,如果没有这些额外的错误,我可以从Get Login控制器中删除LoginModel参数,它可以正常工作。但是因为我想在验证之上传递自定义消息,所以我必须拥有模型参数。但反过来,这意味着即使我加载页面时没有任何内容,它也会显示验证错误(在这种情况下,需要电子邮件)。
我有什么选择?
但是因为我想在验证之上传递自定义消息,所以我必须拥有模型参数。
你实际上没有。您也可以使用模型状态。虽然模型验证错误通常由验证框架自动设置,但在这些错误之上添加您自己的模型错误没有任何问题。
例如,登录POST操作可能如下所示:
[HttpPost]
public async Task<IActionResult> Login(LoginModel model)
{
if (!ModelState.IsValid)
return View(model);
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, model.Password, model.RememberMe);
if (result.Succeeded)
return RedirectToAction(nameof(HomeController.Index), "Home");
}
// add additional error message
ModelState.AddModelError(string.Empty, "Login failed");
return View(model);
}
因此,您不仅可以使用人工错误消息扩展视图模型,以显示自定义模型错误。
我找到了一个有效的解决方案,但这可能不是最干净的。而不是将自定义错误消息放在模型中,通过ViewData传递它,如下所示:
[HttpGet("login")]
[AllowAnonymous]
public IActionResult LoginGet(string errorMessage = null)
{
ViewData["loginErrorMessage"] = errorMessage;
return View();
}
[HttpPost("login")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LoginPost(LoginModel model)
{
if (!ModelState.IsValid)
{
return View("Login", model);
}
...
}
[HttpPost("login")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Whatever(LoginModel model)
{
var error = "The one time login link has expired";
return RedirectToAction("Login", new {errorMessage = error};
}