ResetPassword 功能不使用来自 link 的代码

ResetPassword feature doesn't use code from link

我正在查看一个旧的 MVC 网站。我不明白我的帐户控制器中的以下代码。 (我相信这是由 ASP.NET 生成的代码。)

控制器

//
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
    return code == null ? View("Error") : View();
}

//
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var user = await UserManager.FindByNameAsync(model.Email);
    if (user == null)
    {
        // Don't reveal that the user does not exist
        return RedirectToAction("ResetPasswordConfirmation", "Account");
    }
    var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
    if (result.Succeeded)
    {
        return RedirectToAction("ResetPasswordConfirmation", "Account");
    }
    AddErrors(result);
    return View();
}

查看

@model OnBoard101.Models.ResetPasswordViewModel
@{
    ViewBag.Title = "Reset password";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Reset your password</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Code)
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-success" value="Reset" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

当用户使用“忘记密码”功能然后单击通过电子邮件发送给他们的 link 时,将调用这些方法。

据我所知,POST 处理程序正确检测到 link 中的无效代码(它在代码时产生 无效令牌 错误不是价值)。但我不明白如何。 GET 处理程序似乎简单地丢弃了 code 参数。

我不明白这段代码是如何工作的。 model.Code 是如何填充的?

重置密码功能确实使用来自link的代码。

模型绑定从各种来源检索数据,例如路由数据、表单字段和查询字符串。

它检查查询字符串参数以匹配视图使用的模型上的属性

虽然看起来 code 被控制器 GET 操作丢弃,但 code 仍然是请求的一部分并被视图使用。

并且由于视图明确绑定到模型

@model OnBoard101.Models.ResetPasswordViewModel

其中有匹配的 public Code 属性 (不区分大小写)

public string Code { get; set; }

它将在 GET 期间将其绑定到视图中的模型,然后使用它 (模型) 填充隐藏的表单字段(如视图标记所示)

@Html.HiddenFor(model => model.Code)

现在当表单被提交时,POST 动作会将该字段绑定到回传给动作的模型并执行验证

同样可以用

实现
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code) {
    if (code == null) return View("Error");
    var model = new ResetPasswordViewModel {
        Code = code
    };
    return View(model);
}

但是由于内置模型绑定功能会在未提供模型的情况下初始化模型,因此上面的代码实际上并没有为框架开箱即用的功能添加任何额外内容。