JQuery and Ajax.BeginForm() posting same data twice
Asked Answered
I

3

13

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);
}
Identify answered 4/4, 2012 at 19:30 Comment(0)
D
47

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

Domingo answered 18/1, 2013 at 10:16 Comment(2)
I honestly hoped this was my issue (as in the debugger I can see two of every file for some reaso) but its not.Ulster
Thx for saving my day!Hylomorphism
S
1

I had this same problem today. Ben's answer provided a clue for me, but my problem wasn't as obvious as seeing jquery.unobtrusive-ajax.js twice in the html source. I was converting several standard views to partial views, so I had methods with a return type of ActionResult that were using the View method to return a type of ViewResult:

public ActionResult CreateView()
{
    var model = new CreateViewModel();
    return View("Create", model);
}

In my process of converting to partial views, I made a new .cshtml view file called _Create.cshtml and modified the controller method to:

public ActionResult CreateView()
{
    var model = new CreateViewModel();
    return View("_Create", model);
}

At this point I was experiencing the double posting from an ajax form in the _Create partial view. The solution was to use the PartialView method to return a type of PartialViewResult:

public ActionResult CreateView()
{
    var model = new CreateViewModel();
    return PartialView("_Create", model);
}

It was hard to spot because everything was working fine besides the double-posting of ajax forms, since both ViewResult and PartialViewResult are valid types of ActionResults.

Spiccato answered 5/11, 2018 at 21:40 Comment(1)
This was my issue as well, thanks!Yoruba
S
0

I know this is a very old question but I came across this same problem today. I'm adding the solution I found now just in case someone else comes across this. If you are opening a dialog or page that creates the form then when you close that form (which is what I think the OP is doing) then the events tied to that form don't actually get removed. If you are using jQuery then I found that if you call $('#form').remove() before you actually remove the form from the DOM then those events are removed and you won't get multiple calls to the action. Hope this helps.

Supercargo answered 23/11, 2018 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.