In this recipe, we are going to take a look at how we can override the form submission process. Sometimes you may want to enable the user to POST
a form without refreshing the whole page. I usually do it because I either want to preserve some other piece of information on the page, or because I want to preserve the page's state within the browser. Examples I can think of might be scroll position, or the form exists within a modal created with JavaScript. You might be tempted to achieve a similar result with an IFRAME
, hopefully this recipe will show you that a ASP.NET MVC/jQuery solution is a lot more elegant.
In addition to jQuery 1.4.1, we're going to be using one of the official jQuery plug-ins called jQuery Form. It's in the source code, but it's also available for the following URL— http://jquery.malsup.com/form/.
Article
. The action should look like the following example. The second parameter (btnSubmit
) is entirely optional; this recipe does not use it.[HttpPost] public ActionResult Article(Article article, string btnSubmit) { return View(article); }
ArticleSaved
. So, create a new action in the HomeController
called ArticleSaved
.Controllers/HomeController.cs:
public ActionResult ArticleSaved() {
return View();
}
Article
action that accepts posts and redirects that action to render the new ArticleSaved
action.[HttpPost] public ActionResult Article(Article article, string btnSubmit) { return RedirectToAction("ArticleSaved"); }
Article
action and then redirect to the ArticleSaved
view.We've just implemented a design pattern called Post/Redirect/Get or PRG. Rather than returning the success message in the initial response to the POST, we redirect to another action first. This technique was introduced to prevent the accidental resubmission of HTML forms. If we didn't redirect first and the user tried to refresh the page, the browser will attempt to resubmit the form. Bad, if you’ve just bought a car! http://en.wikipedia.org/wiki/Post/Redirect/Get.
Site.Master
in the Views/Shared
directory. Make some whitespace after the css
link. Then drag the jquery-1.4.1.js
& jquery.form.js
scripts into the head. You may already have a reference to jQuery.Views/Shared/Site.Master: <head runat="server"> <title><asp:ContentPlaceHolder ID="TitleContent" runat="server"/> </title> <link href="/Content/Site.css" rel="stylesheet" type="text/css"/> <script src="/Scripts/jquery-1.4.1.js" type="text/javascript"></script> <script src="/Scripts/jquery.form.js" type="text/javascript"></script> </head>
POST
the data to the action of the form.Views/Home/Article.aspx:
<script language="javascript" type="text/javascript">
$(function () {
$("form").ajaxForm({ target: "#result" });
});
</script>
div
tag to capture the result of our form submission. This tag can go just above the form
tag.Views/Home/Article.aspx:
<div id="result"></div>
Article
page as it currently sits. It should technically work as currently configured. However, the result will be a bit unexpected. The response for the post is currently fed into the div
tag that we just added. The problem is that the current response is an entire page! Let's remedy this by allowing our controller to render a different result depending on the type of request. IsAjaxRequest
that checks for this header in incoming requests. We'll use IsAjaxRequest
to decide which response to send back to the client.Controllers/HomeControllers.cs:
[HttpPost]
public ActionResult Article(Article article) {
if (Request.IsAjaxRequest())
return Content("Article Saved!");
return RedirectToAction("ArticleSaved");
}
_ArticleSaved
. Then take the message that we put in the ArticleSaved
view, and put it into the partial view. Finally, set the ArticleSaved
view to render the _ArticleSaved
partial view. At the end, you should have a view called ArticleSaved
that references a partial view called _ArticleSaved
.Views/Home/ArticleSaved.aspx:
<% Html.RenderPartial("_ArticleSaved"); %>
_ArticleSaved
—this action will return our _ArticleSaved
partial.public ActionResult _ArticleSaved () { return PartialView(); }
_ArticleSaved
action when IsAjaxRequest()
returns true
.Controllers/HomeController.cs:
if (Request.IsAjaxRequest())
return RedirectToAction("_articleSaved");
return RedirectToAction("ArticleSaved");
ArticleSaved
view after submitting the form. But with JavaScript enabled, you should just see the message rendered at the top of the form itself after it is submitted.In this recipe, we have created a form that posts to an action as expected. When the form is submitted, it is then redirected to a successful submission page. With the basic form submission working as expected, we then turn our attention to wiring in some JavaScript to handle posting our form behind the scenes in an Ajax fashion. We then make our controller intelligent enough to respond to the form submission differently, based on whether we used JavaScript or not. This is called progressive enhancement or graceful degradation, depending on whether you are a glass half-full or half-empty sort of developer.