提交后保留查询字符串参数

时间:2018-01-21 17:08:37

标签: asp.net-mvc

在我的网站上我使用MVC身份验证,如果用户想要重置密码,他点击“忘记密码”,然后他通过电子邮件获得一个带有唯一代码的链接来重置他的密码。

我的问题是,如果由于某种原因重置失败(例如 - 密码和密码确认不匹配等),那么它将返回到视图而没有在用户通过电子邮件获得的链接中生成的唯一代码之后重置密码不起作用(code查询字符串参数)

如何在重置失败时将查询字符串保留为唯一代码并将其返回到View?

[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)
      {
           var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
           if (result.Succeeded)
           {
                return RedirectToAction("ResetPasswordConfirmation", "Account");
           }
      }
       ViewBag.Error = "Password reset failed";
       return View();
}

这就是形式:

  <form id="reset-form" method="post" action="Account/ResetPassword">
        @Html.AntiForgeryToken()
        <div class="header">
            <h2>Reset Password</h2>
            @if (!String.IsNullOrEmpty(ViewBag.Error))
            {
                <div class="invalid">
                    @ViewBag.Error
            </div>
            }
        </div>
        <div class="inputField">
            <input type="email" id="email" name="email" placeholder="USERNAME" />
        </div>
        <div class="inputField">
            <input type="password" id="password" name="password" placeholder="PASSWORD" />
        </div>
        <div class="inputField">
            <input type="password" id="confirm-password" name="confirmPassword" placeholder="CONFIRM PASSWORD" />
            <input type="submit"/>
        </div>
    </form>

我需要它返回到这样的视图:

  

〜/帐户/ resetpassword?代码= XYZ

1 个答案:

答案 0 :(得分:1)

除非您进行重定向(不推荐),否则该URL将与您在返回视图时发布的内容保持一致。

但是,问题并不是您需要在操作方法运行后更改URL。您需要将发布的的URL更改为操作方法以包含查询字符串,以便在操作方法返回视图时将其存在。这可以通过简单地更改表单的URL来完成。

  

请注意,您应该从不对MVC视图中的URL进行硬编码。相反,您应始终使用controlleraction和其他路由值来使用UrlHelper(以及相关的扩展方法,例如ActionLink)来解析网址。路由基础结构应该是URL存在的唯一位置,以便可以在一个位置更改它们。

在这种情况下,解决方案是使用Html.BeginForm根据路由构建表单标记。

@using (Html.BeginForm("ResetPassword", "Account", new { code = "xyz" }, FormMethod.Post))
{
    @Html.AntiForgeryToken()
    <div class="header">
        <h2>Reset Password</h2>
        @if (!String.IsNullOrEmpty(ViewBag.Error))
        {
            <div class="invalid">
                @ViewBag.Error
        </div>
        }
    </div>
    <div class="inputField">
        <input type="email" id="email" name="email" placeholder="USERNAME" />
    </div>
    <div class="inputField">
        <input type="password" id="password" name="password" placeholder="PASSWORD" />
    </div>
    <div class="inputField">
        <input type="password" id="confirm-password" name="confirmPassword" placeholder="CONFIRM PASSWORD" />
        <input type="submit"/>
    </div>
}

当然,您也不应该在这里硬编码"xyz",它应该在模型或{{HttpGet ResetPassword方法中传递给视图1}}。

请注意,如果路由定义的ViewBag参数(通常位于url中不包含 RouteConfig.cs的参数,则会自动添加该参数将URL作为查询字符串参数。