Does submit button passes its value to action method, on form submit?

Refresh

April 2019

Views

179 time

1

Update:

What are the control/fields whose value would be submitted when the form is post back?


In an ASP.NET MVC Form, if user double clicks on the submit button, the form would be submitted two times. In order to solve this problem I implemented the solution explained here.

This is my solution, where I disable the submit button on form submit so it cannot be clicked again:

function preventFromBeingDoubleSubmitted() {
    $('form').each(function () {
        $(this).submit(function (e) {
            if ($("form").valid()) {
                // if form is valid, then disable the submit button so it cannot be double clicked (double submitted)
                $(this).find(':submit').attr('disabled', 'disabled');
            }
        });
    });
}

$(document).ready(function () {
    preventFromBeingDoubleSubmitted();
});

This works fine, but I am getting a very strange behavior with ASP.NET Built in, Identity code. My login page, allows user to login with Facebook or Google (each of those buttons are submit buttons):

enter image description here

This is the code which generates the above login form (this is the built-in identity template):

@{
    var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
    if (loginProviders.Count() > 0)
    {
        using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl }))
        {
            @Html.AntiForgeryToken()
            <div class="form-group">
                @foreach (AuthenticationDescription p in loginProviders.OrderBy(o => o.Caption))
                {
                    if (string.Equals(p.AuthenticationType, "google", StringComparison.InvariantCultureIgnoreCase))
                    {
                        <button type="submit" class="external-login-btn btn-google" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">Log in with @p.AuthenticationType</button>
                    }
                    if (string.Equals(p.AuthenticationType, "facebook", StringComparison.InvariantCultureIgnoreCase))
                    {
                        <button type="submit" class="external-login-btn btn-facebook" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">Log in with @p.AuthenticationType</button>
                    }
                }
            </div>
        }
    }
}

The above code, should hit the following Controller Action (built-in identity template):

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
    return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}

After, adding the .js code to prevent double submission, the external login no longer works. The problem is, when user clicks on Log in with Facebook button, the provider name is no longer passed in to ExternalLogin Action.

If I remove preventFromBeingDoubleSubmitted() function, provider name would be passed in ExternalLogin Action method and everything works fine.

What I don't understand is, how is provider passed in to action method at the first place? And why disabling the button prevents provider from being passed in?

2 answers

1

An HTML form is a section of a document containing normal content, markup, special elements called controls (checkboxes, radio buttons, menus, etc.), and labels on those controls. Users generally "complete" a form by modifying its controls (entering text, selecting menu items, etc.), before submitting the form to an agent for processing (e.g., to a Web server, to a mail server, etc.)

Users interact with forms through named controls.

A control's "control name" is given by its name attribute. The scope of the name attribute for a control within a FORM element is the FORM element.

HTML defines the following control types:

  • buttons
  • checkboxes
  • radio buttons
  • menus: Menus offer users options from which to choose. The SELECT element creates a menu, in combination with the OPTGROUP and OPTION elements.
  • input controls (number, text, etc.)
  • hidden controls
  • object controls: Authors may insert generic objects in forms such that associated values are submitted along with other controls. Authors create object controls with the OBJECT element.

Because buttons are controls so the button's value will be posted to the server (if the buttons have name and value like your example). So it is about html specification. NOT asp.net mvc, not Microsoft's specification

You can refer these links for more details

2

I will first answer this question:

What I don't understand is, how is provider passed in to action method at the first place?

You have a button with name="provider" value="@p.AuthenticationType" this code is passing the provider name to your action method.

Next:

And why disabling the button prevents provider from being passed in?

When the form is submitted, the value of disabled fields is not passed to the server. This is the default behaviour.

Now to solve it, we can hide the button instead of disabling it. So in your preventFromBeingDoubleSubmitted() you can change $(this).find(':submit').attr('disabled', 'disabled'); to $(this).find(':submit').hide();

Hope this helps.

Update

To answer a new question about which fields are included in the form data.

  1. <input>
  2. <button>
  3. <option>