Search code examples
c#asp.netasp.net-mvcasp.net-mvc-4post

MVC Post Causes QueryString to Be Lost on Reload of Same View


Please let me explain the setup.

I have a Change Password Controller/Action and View. Here are the Action Signatures in my Account Controller:

public ActionResult ChangePassword(ChangePasswordMessageId? message)

[HttpPost]
public ActionResult ChangePassword(ChangePasswordViewModel model)

When change password is first loaded, I have some data in the querystring. Here is an example:

https://www.mywebsite.com/Account/ChangePassword?mobile=1

Here is the Form declaration from the view.

@using (Html.BeginForm("ChangePassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

The form is submitted with a simple submit button:

<div class="form-group">
  <div class="col-md-offset-2 col-md-4">
    <input type="submit" value="Change Password" class="btn btn-primary btn-block" />
  </div>
</div>

The form has 3 fields: Current Password, New Password, and Confirm Password. If the user fills in all the data correctly, and passes all the client side validation the form works fine. Everything works fine except for one use case.

Suppose the user enters an Old Password value that is not correct. When I get to the HTTPPOST ChangePassword action above, it will fail. This is what that code looks like.

[HttpPost]
            public ActionResult ChangePassword(ChangePasswordViewModel model)
            {   
                if (ModelState.IsValid)
                {
                    try
                    {
                        MembershipUser user = Membership.GetUser();
        //The NEXT line is the one that fails if they supply the wrong Old Password value.
        //The code then falls to the catch condition below.
                        bool changePassword = user.ChangePassword(model.OldPassword, model.NewPassword);
                        if (changePassword)
                        {
                            string path = Url.Action("ChangePassword", new { Message = ChangePasswordMessageId.ChangePasswordSuccess });
                            temp = Request.UrlReferrer.ToString();
                            pos = temp.IndexOf("?");
                            if (pos > 0) path += "&" + temp.Substring(pos + 1);
                            return RedirectToLocal(path);    
                       }
                        else
                        {
                            ModelState.AddModelError("", "Change Password failed.");
                        }
                    }
                    catch //(Exception ex)
                    {
                        ModelState.AddModelError("", "Change Password failed.");
                        //ModelState.AddModelError("", ex.Message);
                    }
                }

                // If we got this far, something failed, redisplay form
    //The original query string will be gone. The URLwill now only show
    //https://www.mywebsite.com/Account/ChangePassword
                return View(model);
            }

Is there away to call "return View(model);" so that the original query string will still be there? I need to maintain the query string from page to page. I have it working everywhere except for this one use case.

Thanks!


Solution

  • If somebody is still looking for this solution, try not supplying controller and action names.

     @using (Html.BeginForm(null, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
        {
            @Html.AntiForgeryToken()