JQuery and Ajax.BeginForm() posting same data twice

dalcantara picture dalcantara · Apr 4, 2012 · Viewed 7.4k times · Source

Ok I'm a total web newbie but I must admit I'm totally hooked now. Here's my problem:

I have a page with an MVCContrib grid and a "Add Accounts" link that brings up an Ajax form wrapped in a JQuery dialog. When I go through the workflow the first time everything works great. I can add a new item and refresh the grid all via JQuery / Ajax (so I think). However, when I try to add the form a second time, the data from the first form is always submitted. I've been looking at the problem for way too long and must admit I'm totally stuck. Btw - I'm sure I'm doing this totally wrong so feel free to suggest anything better.

Here's the form:

@using (Ajax.BeginForm("SaveCheckAccount", "UserManagement", null, new AjaxOptions { OnSuccess = "onAccountAdded", OnFailure = "onAccountAddedFailed"}, new { id = "accountDetails" }))
{
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.Id)
    @Html.HiddenFor(model => model.version)
    @Html.HiddenFor(model => model.User_Id)
    @Html.HiddenFor(model => model.IsDefault)        
    <table>
        <tr>
            <td>
                Account Number
            </td>
            <td>
                @Html.TextBoxFor(model => model.AccountNumber)
                @Html.ValidationMessageFor(model => model.AccountNumber, "*")
            </td>
        </tr>
        <tr>
            <td>
                Routing Number
            </td>
            <td>
                @Html.TextBoxFor(model => model.RoutingNumber)
                @Html.ValidationMessageFor(model => model.RoutingNumber, "*")
            </td>
        </tr>
        <tr>
            <td>
                Account Type
            </td>
            <td>
                @Html.DropDownListFor(model => model.AccountType_Id, new SelectList(@accountTypes, "ID", "Name", Model.AccountType_Id))
                @Html.ValidationMessageFor(model => model.CheckAccountType)
                @Html.ValidationMessageFor(model => model.AccountType_Id, "*")
            </td>
        </tr>
        <tr>
            <td>
                Bank Name
            </td>
            <td>
                @Html.TextBoxFor(model => model.BankName)
                @Html.ValidationMessageFor(model => model.BankName, "*")
            </td>
        </tr>
        <tr>
            <td>
                Account Name
            </td>
            <td>
                @Html.TextBoxFor(model => model.AccountName)
                @Html.ValidationMessageFor(model => model.AccountName, "*")
            </td>
        </tr>
    </table>   
}

<script type="text/javascript">
    $.ajaxSetup({ cache: false });
</script>

This javascript resides in bank.js file

function BindCommands(createUrl) {

      $("#modalAdd").live("click", function (e) {
          var dialogBox = $("<div>");
          e.preventDefault();
          $(dialogBox).dialog({
              autoOpen: false,
              resizable: false,
              title: 'Create Account',
              modal: true,
              show: { effect: "blind", duration: 50 },
              hide: { effect: "blind", duration: 50 },
              open: function (event, ui) {
                  $.ajax(
                      {
                          type: "Get",                          
                          url: createUrl,
                          success: function (result) {
                              $(dialogBox).html(result);
                          }
                      });
              },

              buttons: {
                  Save: function () {
                      $("#accountDetails").submit();
                      $(this).dialog('close');                      
                  },
                  Cancel: function () {
                      $(this).dialog("close");
                  }
              }
          });
          $(dialogBox).dialog('open');
      });
  }

  function onAccountAdded(data, status, xhr) {      
      $("#accounts-grid").html(data);
  };

  function onAccountAddedFailed(data, status, xhr) {
      alert("Failed");      
  };

The for is intially rendered by clicking the add link on this view:

<script type="text/javascript">
    $.ajaxSetup({cache:false});
    $(document).ready(function() {
        var createUrl = '@Url.Action("NewBankAccountDetails", "UserManagement", new {[email protected]})';
        BindCommands(createUrl);
    });

</script>       
@if (Model != null && Model.Id > 0)
{

    <tr>
        <td class="header" colspan="2">
            User Accounts
        </td>
    </tr>
    <tr>
        <td>
            <a href="#" id="modalAdd">Add Account</a>
        </td>
    </tr>

    Html.RenderPartial("_BankAccountGrid", Model.CheckAccounts);
}

Answer

Ben Pretorius picture Ben Pretorius · Jan 18, 2013

I have had the same issue and banged my head against a wall until I noticed the following script being included twice:

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

I had it script set inside my bundle and the view templates also included it which resulted in double post's by the ajax form.

Hope it helps, if not double the bounty:-P