表单验证错误始终在asp.netcore

时间:2018-09-13 07:55:42

标签: validation asp.net-core controller

我有一个简单的Login表单,其中只有一个输入字段:

<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参数,它将很好地工作。但是,由于我想在验证之上传递自定义消息,因此必须具有model参数。但是反过来,这意味着即使我加载的页面中没有任何内容,它也会显示验证错误(在这种情况下,需要使用电子邮件)。

我有什么选择?

2 个答案:

答案 0 :(得分:1)

  

但是当我想在验证之上传递自定义消息时,我必须具有模型参数。

您实际上没有。您也可以为此使用模型状态。虽然模型验证错误通常是由验证框架自动设置的,但在这些错误之上添加您自己的模型错误也没有错。

例如,登录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);
}

因此,您不仅限于显示人为错误消息,还可以使用人为错误消息扩展视图模型。

答案 1 :(得分:0)

我找到了一个可行的解决方案,但这可能不是最干净的。不要将自定义错误消息放入模型中,而是通过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};
}