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

时间:2018-05-09 01:41:51

标签: asp.net-core-mvc asp.net-identity asp.net-core-2.0

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

@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>

正如您所看到的,我创建了一个名为&#34; LoginViewModel&#34;这将检测提交表单中传递的参数

LoginViewModel

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

        [DataType(DataType.Password)]
        public string Password { get; set; }
    }

当用户点击&#34;登录&#34;在表单上,​​我的ASP.NET标记助手指示发布请求将命中&#34;登录&#34; &#34;帐户&#34;内的行动控制器

这是我的&#34;登录&#34;操作

        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);
        }

对象&#34; loginViewModel&#34;我正在传递给#34;登录&#34; action为null,这意味着它不会在用户提交表单时抓取表单数据。

知道我在这里缺少什么,很确定这是愚蠢的事情吗?

2 个答案:

答案 0 :(得分:3)

你错过了输入上的标签助手!!

<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美分:

  • 您无需指明method =“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>
    

答案 1 :(得分:2)

您正在为输入生成手动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">