为什么将表单控件传递给 ViewModel 在 Core 2.0 ASP.NET 不起作用?



我构建了一个简单的 ASP.NET Core 2.0应用程序,我有一个简单的登录视图。我正在使用 ASP.NET 核心身份,这意味着我正在使用"身份用户"类

@model LoginViewModel
<h2 class="my-4 text-center text-lg-left">Before contacting us, please log in or
<a asp-action="Register" asp-controller="Account"> register!</a></h2>
<form asp-action="Login" asp-controller="Account" method="post" role="form">
<!-- To show form error after submission -->
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName">User Name</label>
<input type="text" class="form-control" placeholder="Username">
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password">Password</label>
<input type="password" class="form-control" placeholder="Password">
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Log In!</button>
</form>

如您所见,我创建了一个名为"LoginViewModel"的视图模型,它将检测提交的表单中传递的参数

登录视图模型

public class LoginViewModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
}

当用户点击表单上的"登录"时,我的 ASP.NET 标签助手指示 post 请求将在"帐户"控制器中点击"登录"操作

这是我的"登录"操作

private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
[HttpGet]
public IActionResult Login()
{
return View(new LoginViewModel());
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel loginViewModel)
{
if (!ModelState.IsValid)
{
return View(loginViewModel);
}

var user = await _userManager.FindByNameAsync(loginViewModel.UserName);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, loginViewModel.Password, false, false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError("", "User name/password not found");
return View(loginViewModel);
}

我传递给"登录"操作的对象"loginViewModel"为空,这意味着它在用户提交表单时没有抓取表单数据。

知道我在这里错过了什么,很确定这是愚蠢的东西吗?

您缺少输入上的标记助手!!

<div class="form-group">
<label asp-for="UserName">User Name</label>
<input type="text" class="form-control" placeholder="Username"
asp-for="UserName" />    <!-- You're missing this -->
<span asp-validation-for="UserName" class="text-danger"></span>
</div>

我的2美分:

  • 你不需要指示方法="post"。这是默认方法。此外,您可能还希望指定区域,以防万一您有多个具有相同名称但位于不同区域的控制器。

    <form asp-area="" asp-controller="account" asp-action="login">
    ....
    </form>
    
  • 在标签上使用标记帮助程序时,无需将文本放在两者之间。标记帮助程序将根据您的[Display]注释生成该注释。

    <label asp-for="UserName"></label>
    
  • 如果需要,也可以使用HTML helpers[Display]生成占位符文本。这样,您就不需要对视图上的文本进行硬编码。

    <div class="form-group">
    <label asp-for="UserName"></label>
    <input type="text" class="form-control" asp-for="UserName"
    placeholder="@Html.DisplayNameFor(x => x.UserName)" />
    </div>
    

您正在为输入生成手动 html,并且它们没有name属性,因此它们在提交表单时不会发布值。

更改输入以使用 TagHelpers,这将生成正确的 html,包括用于客户端验证的name属性和data-val-*属性

// <input type="text" class="form-control" placeholder="Username">
<input asp-for="UserName" class="form-control" placeholder="Username">
// <input type="password" class="form-control" placeholder="Password">
<input asp-for="Password" class="form-control" placeholder="Username">

最新更新