The MVC framework: More on AJAX

The last example we’ve looked at showed how we can add AJAX to a MVC app. However, that example probably needs some more work: after all, we also want it to work when the user has Javascript disabled on the browser. The current version isn’t really that far from achieving that objective. Currently, when JS is disabled, you’ll end up having a full postback to the URL specified in the form’s action. Since that is also being used for the AJAX request, then we already have a common action that will be used in both cases: we just need to adapt the server code (notice that you could also use the Url property of the AjaxOptions object to have 2 different urls for each kind of request).

Here’s the current code for the HandleAjaxUpdate method:

public ActionResult HandleAjaxUpdate(User user) {
  Thread.Sleep(2000); //sleeping for seeing message
  ValidateUserId(user); 
  ValidateName(user); 
  return ModelState.IsValid ? 
         View(“Infosaved”) : View("myform", user);
}

See the problem? When we have an AJAX request, everything works as expected and we’re just returning the partial view. But this is not what we want when we have a full postback. If  we could know if the current request uses AJAX, then everything would be really simple: if it uses AJAX, then return the partial view; if not, just return the complete view.

The good news is that you can see if the current request is an AJAX request: just call the Request.IsAjaxRequest (extension) method. It returns true when you’re in an AJAX request (btw, this method returns true when the current request has a X-Requested-With header with the value set to XMLHttpRequest or when there’s a field with that name and value on the current form’s collection). Here’s a solution that might work for this example:

public ActionResult HandleAjaxUpdate(User user) {
  ValidateUserId(user); 
  ValidateName(user); 
  return ModelState.IsValid ?
               (ActionResult)RedirectToAction("PrintInfo")
                     :
               GetAdequateViewForCurrentRequest(user);
}

private ActionResult GetAdequateViewForCurrentRequest(User user) {
  return Request.IsAjaxRequest() ?
                                 View("myform",user) : View("Index",user); 
}

In this case, I’ve opted for redirecting the user into the PrintInfo action when there aren’t any errors there (you could even use TempData if you need to pass info from the current action). When there are errors, we use the IsAjaxRequest method to check if we’re handling an AJAX request. If we are, then we only need to return the partial view (same thing as we saw in the original post); when that doesn’t happen, we need to return a complete view.

To make everything work, we can transform the view into a typed view:

<%@ Page Language="C#"
                MasterPageFile="~/Views/Shared/Site.Master"
                Inherits="System.Web.Mvc.ViewPage<User>" %>

And we also need to make a slight change on the way the partial view is rendered from within the index view:

<% Html.RenderPartial("myform", Model); %>

And that’s it: with a couple of simple changes you have an app which uses AJAX and falls back to a traditional full postback model when there isn’t any JS support on the browser.

And that’s all for today. Keep tuned for more on the MVC framework.

Advertisements

~ by Luis Abreu on March 4, 2009.

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: