While working with MVC3 and Razor views recently, we came across the need to disable the Ajax behaviour in a form when the user pressed a certain submit button. To give you some background, we were working on a Shopping Cart whereby the user had the following possible actions:
- Edit an item,
- Delete an item
- Update the quantity of an item,
- Submit the cart to Checkout
- Clear the cart
- Refresh the cart.
Now, for most cases, we wanted the cart to be refreshed without the user having to see a post back, so Ajax was the best way to handle this, of course. Although the application is based on the Umbraco CMS, we developed the e-Commerce side of things in MVC3 from scratch and integrated it with Umbraco using the excellent MVCBridge add-on. This allowed us to take advantage of all MVC has to offer. However, the solution that follows is not dependant on Umbraco or MVCBridge at all.
Because this is a new project and has no legacy MVC code in it, we are able to take full advantage of the new Unobtrusive Ajax style for binding Ajax to the form. This means that under the hood we are using jquery's ajax engine only, and not the legacy Microsoft one. Here's the basic form:
@using (Ajax.BeginForm(new AjaxOptions { OnSuccess = "updateCart" })) { @Html.RenderFormToken(); <section id="shoppingCart"><h1>Items in your Shopping Cart</h1><table cellpadding="0" cellspacing="0"> @foreach (var item in Model.Items.Values) { // Render the items, including the Edit, Delete and Update submit buttons... }<tr><td colspan="3" class="totalValue">Total Value:</td><td class="totalValue">@Html.DisplayFor(model => model.TotalIncTax) @Html.HiddenFor(model => model.TotalItemCount) @Html.HiddenFor(model => model.TotalIncTax)</td><td class="totalValue"></td></tr></table><span class="submit"><input type="submit" value="Refresh Cart" name="refresh" id="refresh" /><input type="submit" value="Clear" name="reset" id="reset" /><input type="submit" value="Checkout" name="checkout" id="checkout" /></span></section> }
Now, when a user presses any of the submit buttons, the form will
be posted back to the server, and the new page content will be
returned to the updateCart function so that we can update the
user's view without having to refresh the page.
But we want the item Edit and the Checkout buttons to re-direct to a new page instead of submitting back to the shopping cart. For that to happen, we need to do two things (let's focus on the Checkout button, which we want to re-direct to the Checkout page):
- In the ShoppingCartController we need to check which submit button was pressed by inspecting the form elements, and do a Resonse.Redirect() to the appropriate page if the user pressed the Checkout button, for example; and
- Disable the Ajax behaviour when the user presses the Checkout button.
The code to handle the second step is as follows:
// These variables are defined here as they may be referenced in other code blocks. // The $().ready function is used to populate them. var cartSection = null; var eShopCartForm = null; $(document).ready(function () { cartSection = $("#shoppingCart"); eShopCartForm = cartSection.closest("form"); // Disable the ajax behaviour if the checkout button is pressed. We want the form // to submit normally so that the page can be redirected. var checkoutSubmit = cartSection.find("#checkout"); // We supply our own handler for this button to remove the form's ajax submit handler. checkoutSubmit.live("click", function (evt) { // Setting this attribute to false means the ajax form submit handler won't be triggered... eShopCartForm.attr("data-ajax", "false"); }); });
If you care to dig deeper, then I recommend taking a look through the jquery.unobtrusive-ajax.js file that is bundled with the MVC3 projects. Basically though we are changing the data-ajax attribute that is generated on the form element when the user clicks the checkout button so that the ajax submit handler doesn't trigger.
There you have it. Any questions, suggestions, remarks, please leave a comment...
Image may be NSFW.Clik here to view.