-->

14/01/2012

Html.BeginForm() vs Ajax.BeginForm() in MVC3


We know that .BeginForm() extension method will create a form tag thus associating form level methods to the page.
I have been wondering what exactly is the difference between both Html.BeginForm() and Ajax.BeginForm() methods in MVC3.
Read many blogs, and everyone says only one thing, In Ajax forms, forms are submitted asynchronously using Javascript. So, this post is to verify the same thing.


Objective: How both Html and Ajax forms behave in post back and form updation scenarios.
I have done a very simple POC to demonstrate this.

Step 1: Create an MVC application.

Step 2: Now create a View in which Html form is embeded by using Html.BeginForm(). My aim is to redirect the form when Form is submitted.
@{
    ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
    @using (Html.BeginForm("TestHtmlRedirect", "Home", FormMethod.Post, null))
    {
        <input type="submit" value="Html PsBk Click" />
    }
</p>
Step 3: Define both the action methods required for regular View retrieval and form method "TestHtmlRedirect".
        //This section of code is for TestHtmlView.cshtml
        public ActionResult TestHtmlView()
        {
            ViewBag.Message = "This is a HTML form";
            return View();
        }
        [HttpPost]
        public ActionResult TestHtmlRedirect()
        {
            return RedirectToAction("TestAjaxView", "Home", null);
        }
        //End of the section of code for TestHtmlView.cshtml
If you observe the TestHtmlRedirect() method implementation, we are trying to redirect to another view which we defined in our application(TestAjaxView.cshtml).

Step 4: We need to do certain changes inorder to make Ajax forms work properly as expected.
Include below mentioned JS script files in  _Layout.cshtml (MasterPage File).
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
 Make changes in Web.Config to support Javascript execution.
<add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
Step 5: Create an Ajax form by using Ajax.BeginForm() method in a view.
@{
    ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
    @using (Ajax.BeginForm("TestAjaxRedirect", "Home", FormMethod.Post, null))
    {
        <input type="submit" value="Ajax PsBk Click" />   
    }
</p>
Step 6: Define both the action methods for regular View Retrieval and form method TestAjaxRedirect().
        //This section of code is for TestAjaxView.cshtml
        public ActionResult TestAjaxView()
        {
            ViewBag.Message = "This is a AJAX form";
            return View();
        }
        [HttpPost]
        public ActionResult TestAjaxRedirect()
        {
            return RedirectToAction("About", "Home", null);
        }
        //End of Section of code for TestAjaxView.cshtml
If you observe the implementation of TestAjaxRedirect() method, we are trying to redirect to another view (About.cshtml).

Step 7: Lets execute and see, what happens.
 Once i clicked on the button, the Form method "TestHtmlRedirect" is called and the form is redirected to TestAjaxView.cshtml.
Now, the same thing have to happen when i click on Ajax PsBk Click button. The form should be redirected to About.cshtml.
But it dint happened.Even though the form method "TestAjaxRedirect" is called and the redirect staement is executed, the form is not been redirected.
Reason being, the form submission is done asynchronously using Javascript. As we can see the operations are done asynchronously, Ajax forms are suitable in situations, where you need to do modify or save operations asynchronously , without redirecting to any other forms.

Now, we have one more task to perform. Lets test How both Html and Ajax forms behave in case of Updation.
For this task, i created a similar UI in both Html and Ajax forms.

Step 8: Define Model to support the fields shown in above screenshot.
namespace HtmlVsAjaxBeginForm.Models
{
    public class PersonnelModel
    {
        [Required(ErrorMessage="UserName Required.")]
        public string UserName { get; set; }
        [Required(ErrorMessage = "Email id Required.")]
        public string MailAdress { get; set; }
    }
}
Step 9: Define both Html and Ajax views as per the requirement.
HtmlViewModel.cshtml:
@model HtmlVsAjaxBeginForm.Models.PersonnelModel
@{
    ViewBag.Title = "HtmlViewModel";
}
<h2>HtmlViewModel</h2>
@using (Html.BeginForm("HtmlViewModel","Home",null))    
{
    @Html.ValidationSummary(true)
<fieldset>
    <legend>PersonnelModel</legend>    
    <div class="editor-label">
            @Html.LabelFor(model => model.UserName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UserName)
            @Html.ValidationMessageFor(model => model.UserName)
        </div>    
    <div class="editor-label">
            @Html.LabelFor(model => model.MailAdress)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.MailAdress)
            @Html.ValidationMessageFor(model => model.MailAdress)
        </div>
</fieldset>
<p>
    <input type="submit" value="Html Form Action" />
</p>
}
AjaxViewModel.cshtml:
@model HtmlVsAjaxBeginForm.Models.PersonnelModel
@{
    ViewBag.Title = "AjaxViewModel";
}
<h2>AjaxViewModel</h2>
@using (Ajax.BeginForm("AjaxViewModel", "Home", new AjaxOptions { UpdateTargetId = "result" }))    
{
    @Html.ValidationSummary(true)
<fieldset>
    <legend>PersonnelModel</legend>

    <div id="result"></div>
    <div class="editor-label">
            @Html.LabelFor(model => model.UserName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UserName)
            @Html.ValidationMessageFor(model => model.UserName)
        </div>
    
    <div class="editor-label">
            @Html.LabelFor(model => model.MailAdress)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.MailAdress)
            @Html.ValidationMessageFor(model => model.MailAdress)
        </div>
</fieldset>
<p>
    <input type="submit" value="Ajax Form Action" />
</p>
}
Step 10: Define the Form Methods highlighted on the top in yellow.
The main objective of both the Form Methods are to retrieve the content as shown below.
        //HTML Form Method
        //Purpose: Will return the below content, once after the method triggered.
        [HttpPost]
        public ActionResult HtmlViewModel(PersonnelModel Pmodel)
        {
            return Content("Hi " + Pmodel.UserName + ", Thanks for the details, a mail will be sent to " + Pmodel.MailAdress + " with all the login details.", "text/html");
        }
        //AJAX Form Method
        //Purpose: Will return the below content, once after the method triggered.
        [HttpPost]
        public ActionResult AjaxViewModel(PersonnelModel Pmodel)
        {
            return Content("Hi " + Pmodel.UserName + ", Thanks for the details, a mail will be sent to " + Pmodel.MailAdress + " with all the login details.", "text/html");
        }
Step 11: Now execute both the views and try clicking the Buttons. See how both the forms behave.
Html Form before Button click:
Html form Response after execution of form method:
Observe that the button click caused a PostBack and the same view is rendered with what ever content returned by Form Method, highlighted in Yellow on top.
Ajax Form before Button click:
Ajax form Response after execution of form method:
Observe that, the postback didn't happened and the Content is retrieved on to the form in the target control mentioned in Ajax options in definition of Ajax.BeginForm() method.

Now, someone may raise the concern that we can do the same in Htmlform as well.
Yes, we can. We can update the target Control content with out post back. That required writing of a Javascript function which will serialize the data on current html form and send it back to the Form action method. Method will return the response back to Java script function. The response will be read and the required content will be written back to target control using Jquery.
See this post , where we have done the same.

We have learned the basic difference between Html and Ajax forms in both Redirection and Rendering aspects.

We will explore more on how to work in different scenarios with Ajax forms in further posts.
Code:
Click Here
Is it helpful for you? Kindly let me know your comments / Questions.

16 comments:

  1. Very good post. Quite exhaustive.

    ReplyDelete
  2. perfect post for understanding the exact difference B/W Both of them...thanking you

    ReplyDelete
  3. very good post

    ReplyDelete
  4. Great post thanks a lot

    ReplyDelete
  5. great post, thanks for the steps, highlights and screenshots.

    ReplyDelete
  6. When u r coming to NewZealand

    ReplyDelete
  7. The post is very nice and thanks for such a nice explanation. I have a question here is that when the form get submitted using Ajax, the controller action return the content result when we click on button. The how are you assigning that content result to the result div.

    ReplyDelete
  8. Could you please explains how I can manage below scenario:

    1) On successful submitting form, form should be replaced by text lets say "Thanks for submitting"

    2) I'm validating form in controller so if validation fails then the error message should be displayed on top of the form - form should remain as it is.

    Thanks.

    ReplyDelete
  9. Really good explanation with examples

    ReplyDelete