Emulating the UpdatePanel in ASP.NET MVC 1.0 with AjaxHelper

I just finished up a client application based on ASP.NET MVC 1.0 and thought I’d blog about some of the things I really liked.  If you didn’t catch my earlier post titled 5 Reasons You Should Take a Closer Look at ASP.NET MVC and are interested in learning more about what the MVC framework offers I’d recommend reading that first.  The client application my company built required a lot of AJAX functionality behind the scenes and I used jQuery along with MVC controller actions to pass JSON data back and forth in many cases.  However, I did take the UpdatePanel type approach in a few cases since it’s quite easy to do and very efficient as far as the data that gets passed back and forth between the client and server.

ASP.NET MVC 1.0 provides an AjaxHelper class that exposes a BeginForm() method.  HTML controls wrapped in the BeginForm() area are automatically AJAX enabled much like the ASP.NET UpdatePanel.  However, because ASP.NET MVC doesn’t use ViewState or ControlState at all, the calls back to the server are much more efficient when compared to the UpdatePanel (you can use a tool such as Fiddler to verify this:  http://www.fiddlertool.com).  Here are the basic steps to AJAX-enable sections of a view in ASP.NET MVC.

1. Add Ajax.BeginForm into your View

<% using (Ajax.BeginForm("EditCustomerProfile", null,
   new AjaxOptions { UpdateTargetId = "CustomerForm", OnSuccess = "onEditCustomerProfileSuccess" },
   new { id = "EditCustomerProfileForm" }))
   {
%>

<% } %>


BeginForm() has 11 different overloads that can be used.  This example creates an AJAX-enabled section using the AjaxHelper’s BeingForm() method and defines that a controller action named EditCustomerProfile will be called to retrieve the data.  Any route data that needs to be passed can be specified in the second parameter.  The third parameter represents the AjaxOptions that will be used as the client and server interact.  In this case I specify that a control with an ID of CustomerForm will be updated with the data returned from the server.  I also call a JavaScript success callback named onEditCustomerProfileSuccess to perform other necessary actions in the application if the AJAX call returns successfully:

function onEditOfficeProfileSuccess(content)
{
    if ($('#OfficeProfileValSummary').length == 0) //No validation control found so OK
    {
        ClearOfficeProfileControls();
    }
    GetOfficeProfiles();
}

The final parameter represents properties that are added to the form tag generated by BeginForm().  I simply assign the id of the form tag to EditCustomerProfileForm which is done to make it easier to filter controls using jQuery selectors elsewhere in the application.

2. Add the UpdateTargetID div

Once BeginForm() is defined you need to specify the object (div, span or other object) that will receive updates from the server as AJAX calls are made.  In my case I want an end user to complete a form, submit it to the server, validate it, perform business rules there, etc. and then return the form back to the client with a status message about the action.  The form is defined in a user control which is embedded within my ASP.NET MVC view using the HtmlHelper’s RenderPartial() method.  Since the form area gets updated after the call I wrap it with a div that has an ID of CustomerForm (the UpdateTargetID shown above).  Here’s the completed code:

<% using (Ajax.BeginForm("EditCustomerProfile", null,
   new AjaxOptions { UpdateTargetId = "CustomerForm", OnSuccess = "onEditCustomerProfileSuccess" },
   new { id = "EditCustomerProfileForm" }))
   {
%>
    <div id="CustomerForm">
        <% Html.RenderPartial("EditCustomerForm",Model.CustomerViewModel); %>
    </div>
<% } %>


When user submits the form and data returns from the server the CustomerForm div will automatically be updated without having to write any JavaScript code….just like the ASP.NET Web Forms UpdatePanel. The code for the controller action named EditCustomerProfile is shown next.  If everything validates properly it returns the EditCustomerForm user control with a message letting the client know that everything worked.  If errors are found they are added into the model’s error collection and displayed in the form.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditCustomerProfile(Customer customer, string email)
{
    string emailMessage = null;
    try
    {
        //#### Handle Email
        if (!String.IsNullOrEmpty(email) && Regex.IsMatch(email, @"^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$"))
        {
            emailMessage = UpdateEmailAddress(email);
        }
        else //Email address is null or doesn't follow the RegEx pattern
        {
            emailMessage = "Please check that you entered your email address properly.";
        }

        //#### Handle updating Customer object data
        if (emailMessage == null && customer.IsCustomerValid)
        {
            OperationStatus opStatus = _CustomerRepository.Update(customer,
                c => c.CustomerID == customer.CustomerID);
            if (opStatus.Status)
            {
                ViewData["Status"] = "true";
                return View("EditCustomerForm",
                    new CustomerViewModel(_CustomerRepository.Get(c => c.CustomerID == customer.CustomerID), 
                        "Navy", "Your profile information was saved."));
            }
        }
    }
    catch (Exception exp)
    {
        Logger.Log("Error in AccountController.EditCustomerProfile", exp);
    }
    ViewData["Status"] = "false";
    List<RuleViolation> violations = customer.GetRuleViolations().ToList();
    if (emailMessage != null) violations.Add(new RuleViolation("Email", emailMessage));
    ModelState.AddModelErrors(violations);
    return View("EditCustomerForm", new CustomerViewModel(_CustomerRepository.Get(c => c.CustomerID == customer.CustomerID), 
        "Red", "There was a problem updating your profile."));
}

Adding UpdatePanel-like functionality into ASP.NET MVC applications is a snap and allows you to speed-up end user interaction with pages.  I personally like the fact that successful AJAX calls can easily be routed to callbacks without having to worry about wiring up any helper JavaScript objects.

 


Logo


For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit http://www.thewahlingroup.com/.

comments powered by Disqus

2 Comments

Comments have been disabled for this content.