0

I have a route definition using the new MVC5 RouteAttribute that looks like this-

[HttpGet]
[AllowAnonymous, Route("Account/ResetPassword/{user}/{token}", Name = "ResetPasswordForm")]
public async Task<ActionResult> ResetPassword(int user, string token)

This loads a View which contains a form that allows the user to provide a new and confirmation password, and also submits the password reset token and user ID values as hidden fields. The view is accessed on a URL like -

http://www.domain.com/Account/ResetPassword/2/0tLb2N1eVc3a2dHMkxqNVlX.....

With the view code-

@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { role = "Form" }))
{
    @Html.AntiForgeryToken()
    <h2>Enter a new password below</h2>
    <hr />

    @Html.HiddenFor(m => m.User)

    @Html.HiddenFor(m => m.Token)

    <div class="form-group">
        @Html.LabelFor(m => m.Password)
        @Html.PasswordFor(m => m.Password)
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword)
        @Html.PasswordFor(m => m.ConfirmPassword)
    </div>

    @Html.ValidationSummary(true, "", new { role = "status" })

    <div class="form-actions">
        <input type="submit" value="Reset password" class="ui-button" />
    </div>
}

Having provided a defined Action and Controller I was expecting to see the URL -

/Account/ResetPassword/

For the form action. Instead of this I am seeing-

/Account/ResetPassword/2/0tLb2N1eVc3a2dHMkxqNVlX.....

The POST controller action definition looks like this-

 [HttpPost]
 public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
 {

The additional route arguments are causing the POST request to fail with a 404.

I've tried providing "null" as the route value parameter on the BeginForm method, or specifically setting "user" and "token" to empty strings, but in all cases the original GET parameters are retained. The only workaround I have found is to change the name of the POST action entirely, in which case it is rendered as expected-

<form role="Form" action="/Account/ResetUserPassword" method="post">

Is there a way I can keep the same action name for the POST action, but not have the BeginForm method append the extra parameters I do not need? I am prepared to explicitly write this out as a form element if necessary, but is there a way to achieve this using the built in methods? For consistency if nothing else.

pwdst
  • 13,909
  • 3
  • 34
  • 50

2 Answers2

1

Try specifying a route for HTTP Post also

 [HttpPost]
 [Route("Account/ResetPassword")]
 public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
 {
ssilas777
  • 9,672
  • 4
  • 45
  • 68
  • I actually resolved to try this whilst walking to get food at lunch after posting the question - I guess routes from attributes are given higher priority than implicit routes based on controller and action name? Anyway, this worked perfectly and a well deserved up-vote and accept from me with thanks. Also a good reminder for me in taking your problem "away from the desk", as often you can solve it yourself given a new perspective. – pwdst Feb 24 '14 at 12:58
-3

Try this: Add to system.web

<sessionState cookieless="true" regenerateExpiredSessionId="true" />
Jeyhun Rahimov
  • 3,769
  • 6
  • 47
  • 90
  • This is a password reset token and not a cookieless session ID Jhoon. I will edit the question to clarify this - sorry if this wasn't already clear, I had assumed it obvious from the context. – pwdst Feb 24 '14 at 12:50