MVC Form not posting, calling GET

10,054

Solution 1

It's fixed! If anyone can tell me why because I have NFI.......

Changing this line

@using (Html.BeginForm("Manage", "Account", FormMethod.Post, new { @id = "manageAccountFormHolder", @class = "form-horizontal col-sm-8 col-sm-offset-2 v-offset-4" }))

to

@using (Html.BeginForm())

and I'm posting again. Yey, coding genius, 4 hours to post a form! Anyone want to hire me for a job?

EDIT:

So after further digging, the issue was that we had implemented lower case routes. Since the route was being rewritten from /Account/Manage to /account/manage, the post action is never found (finds the get action fine though). Html.BeginForm() was rendering the action in lowercase, whereas Html.BeginForm("Manage", "Account", FormMethod.Post, new{}) wasn't since I specified camel case for the action and controller.

Solution 2

Change your button to input

<input class="btn btn-default" type="submit" value="Save Changes" />
Share:
10,054
garethb
Author by

garethb

Updated on June 28, 2022

Comments

  • garethb
    garethb almost 2 years

    I can't get my form to call the POST action on my controller.

    My page code

    @model My.Models.ManageUserViewModel
    
    @using (Html.BeginForm("Manage", "Account", FormMethod.Post, new { @id = "manageAccountFormHolder", @class = "form-horizontal col-sm-8 col-sm-offset-2 v-offset-4" }))
        {
            @Html.AntiForgeryToken()
            <h4 class="text-center">Change Password</h4>
    
            <div class="form-group">
                @Html.LabelFor(m => m.OldPassword, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.PasswordFor(m => m.OldPassword, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.NewPassword, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
                </div>
            </div>
    
            <h4 class="text-center v-offset-4">Edit Personal Details</h4>
    
            <div class="form-group">
                @Html.LabelFor(m => m.FirstName, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-4">
                    @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control", @placeholder = "First name" })
                </div>
                <div class="col-sm-5">
                    @Html.TextBoxFor(m => m.LastName, new { @class = "form-control", @placeholder = "Last name" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.Mobile, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    <input class="form-control" id="manageMobile" name="manageMobile" type="tel">
                    @Html.TextBoxFor(m => m.Mobile, new { @class = "form-control", @placeholder = "First name" })
                    <p class="help-block">For authorisation code. We will never share or display your mobile number.</p>
                </div>
            </div>
    
            <h4 class="text-center v-offset-4">Edit Address</h4>
    
            <div class="form-group">
                @Html.LabelFor(m => m.Address1, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-2">
                    @Html.TextBoxFor(m => m.Address1, new { @class = "form-control"})
                </div>
                <div class="col-sm-7">
                    @Html.TextBoxFor(m => m.Address2, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.TownSuburb, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.TownSuburb, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.StateRegion, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.StateRegion, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.PostCode, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.PostCode, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(m => m.Country, new { @class = "col-sm-3 control-label" })
                <div class="col-sm-9">
                    @Html.TextBoxFor(m => m.Country, new { @class = "form-control" })
                    @Html.HiddenFor(m => m.CountryIso, new { @class = "form-control" })
                </div>
            </div>
    
            <div class="text-center">
                <button class="btn btn-default" type="submit">Save Changes</button>
            </div>
        }
    

    My Model

    public class ManageUserViewModel
    {
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Current password")]
        public string OldPassword { get; set; }
    
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { get; set; }
    
        [DataType(DataType.Password)]
        [Display(Name = "Confirm New Password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    
        [Required]
        [Display(Name = "Full Name")]
        public string FirstName { get; set; }
    
        [Required]
        public string LastName { get; set; }
    
        [Required]
        [Display(Name = "Mobile Number")]
        public string Mobile { get; set; }
    
        [Display(Name = "Street Address")]
        public string Address1 { get; set; }
    
        public string Address2 { get; set; }
    
        [Display(Name = "City")]
        public string TownSuburb { get; set; }
    
        [Display(Name = "State")]
        public string StateRegion { get; set; }
    
        [Display(Name = "Postcode")]
        public string PostCode { get; set; }
    
        [Display(Name = "Country")]
        public string Country { get; set; }
    
        public string CountryIso { get; set; }
    }
    

    My Controller actions

    [HttpGet]
    public ActionResult Manage(ManageMessageId? message)
    {
        return View();
    }
    
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Manage(ManageUserViewModel model)
    {
        //Save changes code here
        //Redirect
    }
    

    It won't validate either. If I leave one of the required fields blank, no validation error shows.

    In Fiddler, I see that the form is posting to the server, but the GET method is still called? See Fiddler raw below, this still calls the GET method (I updated my model to only one property to make it simpler).

    POST https://localhost:44301/Account/Manage HTTP/1.1
    Host: localhost:44301
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: https://localhost:44301/account/manage
    Cookie: __RequestVerificationToken=xxxx..........
    Connection: keep-alive
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 20
    
    OldPassword=dfgdfgdg
    
    • Shaun Luttin
      Shaun Luttin about 9 years
      What is the structure of ManageMessageId?
    • garethb
      garethb about 9 years
      Its an enum......... public enum ManageMessageId { ChangePasswordSuccess, SetPasswordSuccess, RemoveLoginSuccess, Error }
    • SBirthare
      SBirthare about 9 years
      @garethb - Your code works absolutely fine with no changes. You should look for error in browser console.
    • garethb
      garethb about 9 years
      @SBirthare - See update, Fiddler shows the form posting with data. But my GET action is hit not POST(breakpoint in both actions). Could it be HTTPS not allowing post?
    • Anuraj
      Anuraj about 9 years
      Did you tried changing input type="submit" - stackoverflow.com/a/3543695/38024
    • garethb
      garethb about 9 years
      @Anuraj - yeah, see answer posted below
    • SBirthare
      SBirthare about 9 years
      Just to try, Can i suggest you change you POST action name and use it accordingly in the view and see if that makes a difference.
    • garethb
      garethb about 9 years
      @SBirthare - Yup, tried that and got resource cannot be found. As soon as I changed the newly named method to allow GET, it found it ok. Sp the problem is only with posting!
    • SBirthare
      SBirthare about 9 years
      Its weird and something related to your setup. Can you try, adding a new controller and move GET and POST there.
    • Daniel Stackenland
      Daniel Stackenland about 9 years
      Something weird on the serverside, some caching problems maybe...? shutdown app pool & w3wp. Clean+ Rebuild, (maybe too obvious)
    • garethb
      garethb about 9 years
      @SBirthare - Thanks, your last comment led to a 'solution'
    • SBirthare
      SBirthare about 9 years
      Glad it helped. What was the problem/solution?
    • garethb
      garethb about 9 years
      @SBirthare - See my answer below. Moving it to a new controller and having it work led me to an answer of sorts
  • Mairaj Ahmad
    Mairaj Ahmad about 9 years
    ok can you remove the Get Method to check what error you get when you post the form ?
  • garethb
    garethb about 9 years
    I put the GET back in and changed the name of the action on the POST to ManageSave (in controller and form action) and also got resource cannot be found?
  • Mairaj Ahmad
    Mairaj Ahmad about 9 years
    Only remove Get and don't rename anything.
  • garethb
    garethb about 9 years
    Yeah, tried that first. thats where I got the resource cannot be found error. So it recognizes that the action is post only.Tried the name change after.
  • Mairaj Ahmad
    Mairaj Ahmad about 9 years
    I copied your code and it is working perfectly fine.
  • garethb
    garethb about 9 years
    Yeah, I was pretty sure the code is solid. I'm at a loss
  • Mairaj Ahmad
    Mairaj Ahmad about 9 years
    In fiddler it is saying https, Shouldn't this be http ?
  • SBirthare
    SBirthare about 9 years
    Weird... I can understand your frustration, we have to see such days in programming sometimes. May be someone else would through some light on what was the real issue?
  • Shaun Luttin
    Shaun Luttin about 9 years
    In your original question, what was the indication that the POST wasn't working. I.e. did you receive a blank page? Did you have a break-point in ActionResult Manage(ManageUserViewModel model) that wasn't hit?
  • garethb
    garethb about 9 years
    @ShaunLuttin - I had a break point in both the post and get actions. Only get was hit. Fiddler told me the form was posting from the browser.
  • garethb
    garethb about 9 years
    I would have thought the form actions would be the other way around in your fiddle? The second form action has the index action where I would have thought the first should. My form posts now using BeginForm(HtmlHelper), however as soon as I use BeginForm(HtmlHelper, String, String, FormMethod, IDictionary) without changing anything else, get is called. I might dig deeper into the issue when I have time!
  • Manpreet Singh Dhillon
    Manpreet Singh Dhillon almost 6 years
    when you explicitly give action name and controller name then form posts to that particular controller and action. When you omit action name and controller name then form posts to the URL. This is the only difference i am seeing here. I guess your controller name might have created problem.
  • Savage
    Savage about 4 years
    Correct on the lowercase issue. See the answer here for a solution on how to only convert GET urls to lowercase, which resolves the issue: stackoverflow.com/questions/878578/…