Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery and Ajax.BeginForm() posting same data twice

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);
}
like image 698
dalcantara Avatar asked Apr 04 '12 19:04

dalcantara


1 Answers

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.

like image 118
AnalogWeapon Avatar answered Oct 20 '22 18:10

AnalogWeapon