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 {userId=@Model.Id})';
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);
}
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
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 ActionResult
s.
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.