ASP.NET MVC пост контроллер действие вызывается несколько раз

У меня есть приложение MVC, которое представляет собой очень простую форму из 6 полей. Данные формы сохраняются в моей базе данных с помощью Entity Framework. Большую часть времени данные сохраняются должным образом без проблем, но появляются случайные дубликаты. Сначала я подумал, что это проблема EF с дубликатами (иногда 1,3,5 одной и той же записи), сохраняемыми с отметкой времени менее секунды, разделяющей их. Но я запустил модульный тест и вытащил все ту же логику, которая находится в моем действии контроллера, чтобы сохранить данные, и мои данные никогда не дублируются. У меня есть JQuery, который отключает кнопку Отправить, поэтому я знаю, что она не связана с несколькими щелчками.

Итак, мой вопрос: возможно ли, что мои контроллеры POST action могут вызываться много раз через некоторое неизвестное поведение? Я не могу реплицировать проблему в VS, когда я устанавливаю точку останова в моем действии контроллера, где данные сохраняются. Я также считаю, что это трудно воспроизвести в целом и совершенно случайным. Кто-нибудь сталкивался с этим когда-либо или есть какие-либо предложения? Это происходит во всех браузерах (FF, IE, Chrome). Спасибо

Я запустил свою заявку через fiddler и иногда, когда я отправляю свою форму, я вижу 2 запроса на публикацию на 1 одном щелчке кнопки.

Код

@model PersonViewModel
@using (Html.BeginForm())
    {
    @Html.AntiForgeryToken()

<div class="form-horizontal">


    @Html.ValidationSummary(false, "The following errors have occurred:", new { @class = "alert alert-danger", @role = "alert" })



    <hr />

        <p>Please enter your personal details below. (* denotes required field)</p>

        <div class="form-group">
            @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @title = "Legal First Name" } })
                @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })

            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.MiddleName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.MiddleName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @placeholder = "enter 'None' if none", @title = "Legal Middle Name" } })
                @Html.ValidationMessageFor(model => model.MiddleName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control", @maxlength = "50", @title = "Legal Last Name" } })
                @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })


            </div>
        </div>



        <div class="form-group" id="EmailGroup">
            @Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { @class = "control-label col-md-2", @id = "EmailLabel" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "form-control", @maxlength = "100", @title = "Email Address" } })
                @Html.ValidationMessageFor(model => model.EmailAddress, "", new { @class = "text-danger" })


            </div>
        </div>

        </div>





        <div class="form-group">
            <div class="col-md-2"></div>
            <div class="col-md-8">
                <input type="submit" value="Submit" id="affSubmit" class="btn btn-primary btn-md" />
            </div>
        </div>

    </div>


                    }


@section Scripts {
@Scripts.Render("~/bundles/jqueryval")

@Scripts.Render("~/Scripts/Custom.js")



}

Макет.cshtml

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-default"> 

</div>
<div class="container body-content">
    @RenderBody()
    <hr />
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jquery-ui")
@RenderSection("scripts", required: false)

Традиция.js

$().ready(function () {




$('form').submit(function (e) {

    if ($('form').valid()) { //make sure form is valid

                $('#affSubmit').prop('disabled', true);
                $('#affSubmit').val("Please wait...");
                this.submit();


        }


    }




});

ControllerAction

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(PersonModel model)
    {

        try
        {

                if (ModelState.IsValid)
                {

                    PersonBLL bll = new PersonBLL();
                    PersonModel result = bll.SavePerson(model);

                    if (result.PersonID > 0)
                    {
                        return View("CreateSuccess");
                    }
                    else
                    {
                        ModelState.AddModelError("SaveError", "An error occurred while attempting to save, please try again later.");
                    }

                }

        }
        catch (Exception ex)  //unexpected error so log it, and redisplay form
        {
            Common.HandleException(ex);
            ModelState.AddModelError("SaveError", "An error occurred while attempting to save, please try again later.");

        }


        //if we get here reshow page
        return View(model);


    }

1 ответ

  1. Используйте preventDefault при отправке с jQuery
    добавьте это в cutsom.JS файл

    $().ready(function () {
       // not here
       $('form').submit(function (e) {
       e.preventDefault();// but here
       // the rest of your code here
       }
    }
    

    Сначала я отредактировал свой ответ, e.preventDefault идет в submit eventhandler. Поведение по умолчанию формы должно быть отправлено, когда вы нажмете кнопку Отправить, поэтому ваша форма будет отправлена дважды один раз из-за поведения по умолчанию и второй с вашим кодом this.представить();
    e.preventDefault отменяет поведение по умолчанию события submit, поэтому форма отправляется только с кодом.