31

I am rendering a form in Asp.net MVC with a submit button. The page redirects after successful record addition into the database. Following is the code :-

[HttpPost]
public ActionResult Create(BrandPicView brandPic)
{
    if (ModelState.IsValid)
    {
        if (!String.IsNullOrEmpty(brandPic.Picture.PictureUrl))
        {
            Picture picture = new Picture();
            picture.PictureUrl = brandPic.Picture.PictureUrl;
            db.Pictures.Add(picture);
            brandPic.Brand.PictureId = picture.Id;
        }
        db.Brands.Add(brandPic.Brand);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();
}

But, while testing, I saw that if the form is clicked again and again, the multiple entries are submitted and saved into the database.

How can i make sure that if the form has been submitted once to the server, then no duplicates are submitted.

Pankaj Upadhyay
  • 12,966
  • 24
  • 73
  • 104
  • 1
    This has already been asked a number of times before: http://stackoverflow.com/questions/2324931/duplicate-form-submission-in-spring – Kane Jan 06 '12 at 12:48
  • @Kane , +1 and sorry. I always check if the question has been asked before, but may be it's time i change my spectacles number ;-) ..... – Pankaj Upadhyay Jan 06 '12 at 13:05
  • Possible duplicate of [How do I prevent multiple form submission in .NET MVC without using Javascript?](https://stackoverflow.com/questions/4250604/how-do-i-prevent-multiple-form-submission-in-net-mvc-without-using-javascript) – KyleMit Sep 19 '17 at 12:33

7 Answers7

83

I don't think this is quite a duplicate of the answer referenced in the comment, since the link is for spring MVC, and this question is for .NET MVC.

I actually spent a few hours on this a while back, and came up with the following. This javascript hooks nicely with the unobtrusive jquery validation, and you can apply it to any form that has <input type="submit". Note that it uses jquery 1.7's on function:

$(document).on('invalid-form.validate', 'form', function () {
    var button = $(this).find(':submit');
    setTimeout(function () {
        button.removeAttr('disabled');
    }, 1);
});
$(document).on('submit', 'form', function () {
    var button = $(this).find(':submit');
    setTimeout(function () {
        button.attr('disabled', 'disabled');
    }, 0);
});

The setTimeouts are needed. Otherwise, you could end up with a button that is disabled after clicked even when client-side validation fails. We have this in a global javascript file so that it is automatically applied to all of our forms.

Update 16 Nov 2020 by @seagull :

Replaced selector input[type="submit"] with :submit so it will work with <button type="submit" /> as well

Seagull
  • 3,319
  • 2
  • 31
  • 37
danludwig
  • 46,965
  • 25
  • 159
  • 237
  • Before, i try this out, i want to let you know that my application uses the jquery-1.5.1 as added by VS at the start. Replacing it with 1.7 version effect my application? – Pankaj Upadhyay Jan 06 '12 at 14:14
  • I can't say, but it shouldn't. If you want to stick with 1.5, you could just change `on` to `live`. – danludwig Jan 06 '12 at 14:18
  • 7
    This is good, but it should be mentioned that you could be using buttons, which this wouldn't find. If you are using both inputs and buttons, you would have to search both like, var button = $(this).find('input[type="submit"], button[type="submit"]'); – erosebe Feb 09 '15 at 21:32
  • I also like to use `$(document.body).append("stuff");` in the setTimeout of the second .on and `$(".whatever").remove();` in the setTimeout of the first .on to grey out the page and put a nice spinning gif in the middle with a friendly message for long-running operations like file uploads. – nmit026 Oct 12 '16 at 05:26
10

The solution for mvc applications with mvc client side validation should be:

$('form').submit(function () {
    if ($(this).valid()) {
        $(':submit', this).attr('disabled', 'disabled');
    }
});
drgnik
  • 101
  • 1
  • 4
  • This method is clean and simple because it only disables the button if the client-side validation passed and it works on non-ajax forms since I don't have the luxury of time to refactor a bunch of non-ajax forms. – TechSavvySam Oct 30 '18 at 14:54
  • Nice clean drop-in indeed! It can be improved slightly by adding `.attr('value', 'Please wait...')` to the chain (or similar), to encourage users not to hit `F5` for long lasting form submissions (eg: files). – easuter May 20 '20 at 17:54
6

Disable the button on Submit clicked. This can be done using JQuery/Java Script.

Look at this example on how to do this.

Maheep
  • 5,539
  • 3
  • 28
  • 47
2

You can use this one. It includes unobtrusive jQuery validation.

$(document).on('submit', 'form', function () {
    var buttons = $(this).find('[type="submit"]');
    if ($(this).valid()) {
        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', true);
        });
    } else {
        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', false);
        });
    } });

For jQuery validation please incllude

~/Scripts/jquery.validate.min.js
~/Scripts/jquery.validate.unobtrusive.min.js
Sasa Tancev
  • 645
  • 5
  • 5
1

You can use ajax.BeginForm insted of html.BeginForm to achieve this, if you use OnSuccess insted of OnBegin you can be sure that your method execute successful and after that your button turn to deactivate,with ajax you stay in current view and you can update your current view instead of redirection

@using (Ajax.BeginForm(
new AjaxOptions
{
    HttpMethod = "post",
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "dive",
    OnBegin="deactive"
}))
{
//body of your form same as Html.BeginForm
<input type="submit" id="Submit" value="Submit" />
}

and use this jquery in your form:

<script type="text/javascript" language="javascript"> function deactive() { $("#Submit").attr("disabled", true); }</script>

be careful for using ajax you have to call this scrip in the end of your page

<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Ali
  • 430
  • 3
  • 16
0
window.onload = function () {
            $("#formId").submit(function() {// prevent the submit button to be pressed twice
                $(this).find('#submitBtnId').attr('disabled', true);
                $(this).find('#submitBtnId').text('Sending, please wait');
            });
        }
Hello Hack
  • 107
  • 5
0

Disabling the button is fine via JavaScript but what if the user has it disabled or they bypass it? If you use client side security then back it up with server side. I would use the PRG pattern here.

eth0
  • 4,977
  • 3
  • 34
  • 48
  • From the link you referenced -- The PRG pattern cannot address every scenario of duplicate form submission. Some known duplicate form submissions that PRG cannot solve are: ...if a web user clicks a submission button multiple times before the server response loads (may be prevented by using JavaScript to disable the button after the first click). – danludwig Jan 06 '12 at 14:32
  • @olivehour correct, I am stupid and didn't read the question properly. – eth0 Jan 09 '12 at 11:47