【问题标题】:Avoiding Duplicate form submission in Asp.net MVC by clicking submit twice通过单击两次提交避免在 Asp.net MVC 中重复提交表单
【发布时间】:2012-01-06 12:43:50
【问题描述】:

我在 Asp.net MVC 中呈现一个带有提交按钮的表单。成功添加记录到数据库后,页面重定向。以下是代码:-

[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();
}

但是,在测试时,我看到如果一次又一次地单击表单,则将多个条目提交并保存到数据库中。

如何确保如果表单已提交一次到服务器,则不会提交重复项。

【问题讨论】:

标签: asp.net-mvc-3 forms


【解决方案1】:

我不认为这与评论中引用的答案完全重复,因为该链接适用于 spring MVC,而这个问题适用于 .NET MVC。

实际上,我不久前在这方面花了几个小时,并想出了以下内容。此 javascript 与不显眼的 jquery 验证很好地挂钩,您可以将其应用于任何具有 <input type="submit" 的表单。请注意,它使用 jquery 1.7 的 on 函数:

$(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);
});

需要 setTimeouts。否则,即使客户端验证失败,您也可能会得到一个在单击后被禁用的按钮。我们在一个全局 javascript 文件中拥有它,因此它会自动应用于我们所有的表单。

@seagull 于 2020 年 11 月 16 日更新:

将选择器 input[type="submit"] 替换为 :submit,因此它也可以与 <button type="submit" /> 一起使用

【讨论】:

  • 在我尝试这个之前,我想让你知道我的应用程序使用 VS 在开始时添加的 jquery-1.5.1。用 1.7 版本替换它会影响我的应用程序吗?
  • 我不能说,但不应该。如果您想坚持使用 1.5,您可以将 on 更改为 live
  • 这很好,但应该提到您可能正在使用按钮,这是找不到的。如果您同时使用输入和按钮,则必须同时搜索 var button = $(this).find('input[type="submit"], button[type="submit"]');跨度>
  • 我也喜欢在第二个 .on 的 setTimeout 中使用 $(document.body).append("stuff"); 和在第一个 .on 的 setTimeout 中使用 $(".whatever").remove(); 来使页面变灰并在中间放一个漂亮的旋转 gif为文件上传等长时间运行的操作提供友好的消息。
【解决方案2】:

带有mvc客户端验证的mvc应用的解决方案应该是:

$('form').submit(function () {
    if ($(this).valid()) {
        $(':submit', this).attr('disabled', 'disabled');
    }
});

【讨论】:

  • 这个方法干净简单,因为它只在客户端验证通过时禁用按钮,并且它适用于非 ajax 表单,因为我没有时间重构一堆非 ajax 形式。
  • 确实很干净!可以通过将.attr('value', 'Please wait...') 添加到链(或类似的)来稍微改进它,以鼓励用户不要点击F5 进行持久的表单提交(例如:文件)。
【解决方案3】:

在点击提交时禁用按钮。这可以使用 JQuery/Java 脚本来完成。

查看this example 了解如何执行此操作。

【讨论】:

    【解决方案4】:

    你可以用这个。它包括不显眼的 jQuery 验证。

    $(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);
            });
        } });
    

    对于 jQuery 验证,请包括

    ~/Scripts/jquery.validate.min.js
    ~/Scripts/jquery.validate.unobtrusive.min.js
    

    【讨论】:

      【解决方案5】:

      您可以使用 ajax.BeginForm insted of html.BeginForm 来实现这一点,如果您使用 OnSuccess insted of OnBegin 您可以确保您的方法执行成功,然后您的按钮变为停用,使用 ajax 您停留 在当前视图中,您可以更新当前视图而不是重定向

      @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" />
      }
      

      并在您的表单中使用此 jquery:

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

      小心使用 ajax,您必须在页面末尾调用此脚本

      <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
      

      【讨论】:

        【解决方案6】:

        通过 JavaScript 禁用按钮很好,但如果用户禁用它或绕过它怎么办?如果您使用客户端安全性,则使用服务器端进行备份。我会在这里使用PRG pattern

        【讨论】:

        • 来自您引用的链接——PRG 模式无法解决重复表单提交的所有情况。 PRG 无法解决的一些已知的重复表单提交是: ...如果 Web 用户在服务器响应加载之前多次单击提交按钮(可以通过在第一次单击后使用 JavaScript 禁用按钮来阻止)。
        • @olivehour 正确,我很愚蠢,没有正确阅读问题。
        【解决方案7】:
        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');
                    });
                }
        

        【讨论】:

          猜你喜欢
          • 2018-06-07
          • 1970-01-01
          • 2014-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-05
          • 1970-01-01
          相关资源
          最近更新 更多