Submitting an MVC Ajax.BeginForm Using JavaScript and jQuery
April 5, 2011 8 Comments
The Ajax.BeginForm() helper method in ASP.Net MVC generates a bit of inline JavaScript attached to the onsubmit event of the form. When the form is submitted in the usual manner with a submit button the request is sent using XMLHttpRequest and the result is returned into the <DIV /> of your choice. However, if you want try to submit the form using JavaScript things are less tidy.
For my example, imagine a user account management tool that displays a grid of accounts and has a number batch of operations that you can perform against the grid data in an Ajax-y manner.
The idea here is that you could, for example, check a number of accounts and then click disable and those accounts would be disabled. The result of your operation gets written into a notification <DIV />.
Here’s the naïve implementation for submitting an MVC Ajax form.
jQuery().ready(function () { //other stuff including jqGrid initialization here... //'grid' is the id of the jqGrid table element //'disableKeys' is the id of the Ajax form we are submitting. $('form#disableAccounts').find('a.submit-link').click(function () { //work to set the state of the form before sending it to the server here... $('form#disableAccounts').submit(); }); )};
Unfortunately, this doesn’t do at all what we want. What you end up with is the text that was intended for the notification <DIV /> replacing the entire window contents. In other words, a classic POST. But wait, there’s more.
What actually happens is that the request is submitted twice! The first version is Ajax and the second is classic POST, interrupting the Ajax response.
The First Solution
My initial approach to solving this double-submit problem hinged on leveraging the fact that Ajax.BeginForm() generates a <FORM /> tag with some JavaScript attached to the onsubmit event to handle the Ajax behavior. Why not just trigger the onsubmit event directly?
jQuery().ready(function () { //other stuff including jqGrid initialization here... //'grid' is the id of the jqGrid table element //'disableKeys' is the id of the Ajax form we are submitting. $('form#disableAccounts').find('a.submit-link').click(function () { //work to set the state of the form before sending it to the server here... $('form#disableAccounts').trigger('onsubmit'); }); )};
This works great except in Safari where nothing happens at all.
The Final Solution
I tried a number of different techniques to suppress the default form POST behavior. The one that worked in IE, Firefox, Chrome and Safari is to attach a new event handler to the submit event that always returns false.
jQuery().ready(function () { //other stuff including jqGrid initialization here... //prevent the form from submitting in a non-Ajax manner for all browsers $('form#disableAccounts').submit(function (event) { eval($(this).attr("submit")); return false; }); //'grid' is the id of the jqGrid table element //'disableKeys' is the id of the Ajax form we are submitting. $('form#disableAccounts').find('a.submit-link').click(function () { //work to set the state of the form before sending it to the server here... $('form#disableAccounts').submit(); }); )};
This works to suppress the second standard POST and allow the ASP.Net Ajax behavior to complete as expected.