Submitting an MVC Ajax.BeginForm Using JavaScript and jQuery

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.account-mgmt

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.

debug-double-post

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.

Advertisements

8 Responses to Submitting an MVC Ajax.BeginForm Using JavaScript and jQuery

  1. Phil Webb says:

    Thank you, thank you, thank you! I’ve spent a day reading so many posts on IE8’s double submit problems, but was unable to find anything that matched my problem. Finally got my search text right and found your post which solved my problem.

  2. gomars says:

    Thank you so much!!! I’ve been troubled with this issue for a long time. :))))

  3. Steve says:

    I just tried your final solution, but my form is still submitting the entire page when I call form.submit(); Any ideas what I’m doing wrong?

  4. Lasse Espeholt says:

    The final solution didn’t work for me. So I ended up doing my own submit logic for Asp.net MVC 3 with unobtrusive javascript:

    (function ($) {
    $.fn.submitMVC = function () {
    var form = this;

    if (form.attr(‘data-ajax-mode’) !== ‘replace’)
    submitFailure(undefined); // Not implemented

    if (form.attr(‘method’) !== ‘post’)
    submitFailure(undefined); // Not implemented

    var jqxhr = $.post(form.attr(‘action’), form.serialize(), function(data) {
    $(form.attr(‘data-ajax-update’)).html(data);
    })
    .success(eval(form.attr(‘data-ajax-success’)))
    .error(eval(form.attr(‘data-ajax-failure’)))
    }
    })(jQuery);

    I’ve only implemented the features I needed, but the rest should be trivial.

  5. rj says:

    Thank you so much! Worked great and the explanation was wonderful.

  6. Matthew Eno says:

    Thanks so much. I’ve spent AGES trying to sort this out, and your solution worked first time. Good work.

  7. Naresh says:

    Thanks , it working .
    But, i have one more problem.
    How i get that post request success/failure/complete in jquery ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: