MVC AJAX Sites That Gracefully Degrade
(Oct 21 2008 - 10:08:37 PM
by Timothy Khouri
) - [print article
As AJAX-enabled web sites continue to grow in popularity, the development community continues to try to solve the common problems of using AJAX. One big concern that used to require a lot of work is that of gracefully degrading your AJAX site for non-capable browsers. Thankfully, the ASP.NET MVC framework makes this an easy task.
Our demo site will have a "news" section where users can view the latest news, and subscribe to our newsletter. This functionality will be provided through AJAX calls. Our goal is to achieve this same functionality for non-ajax-enabled browsers without duplicating a lot of work.
AJAX Extensions in ASP.NET MVC
If you've been playing around in ASP.NET MVC even a little, you likely have noticed how simple it is to use AJAX in your web app. Take for example creating a link to our "News List" page (which is actually in our demo app). To make a standard link that goes to the "News" controller and executes the "List" action would look something like this:
<%= Html.ActionLink("View News", "List", "News") %>
But what would we do if we wanted that link to use AJAX to pull the latest news and update a simple <div> on our page? All we would have to do is use the "Ajax.ActionLink" method, and supply an extra parameter that has the 'AJAX options' in there. Here's what that would look like:
Ajax.ActionLink("View News", "List", "News",
HttpMethod = "POST",
UpdateTargetId = "news-list",
InsertionMode = InsertionMode.Replace,
Coding Your ActionMethod to Detect AJAX Requests
Because one of our main goals is not to have to duplicate a lot of work, we want the same code to run for the user if he's using AJAX or not. The only part that has to change really is the "View" that gets sent back to the client. In order to accomplish this, we're going to use the "IsMvcAjaxRequest" method that comes in the System.Web.Mvc.Ajax namespace (in the AjaxExtensions class).
Update: Oct 22 2008
Originally, I didn't know about the "IsMvcAjaxRequest" method, so I had a code snippet here that showed how to make our own method by looking for the "__MVCASYNCPOST" form field. Due to a comment below, I've removed the code snippet that had the extension method here.
As was mentioned by Jonathan Carter (who's a Technical Evangelist for Microsoft), the MVC Beta already includes the extension method above. Now all we have to do is call the "IsMvcAjaxRequest" method. Example:
And then to use it in our ActionMethod, here's what we would do:
public ActionResult List()
this.ViewData.Model = this.GetNewsItems();
if (this.Request.IsMvcAjaxRequest() == false)
Notice that we don't have to duplicate any logic for getting the latest news. The only bit of custom logic that is needed is to determine which view to send. This can be done for form posts too (as you can see in the screen shots below or by downloading the project at the end of the article). Here's what the results of the above will look like for an AJAX enabled, and a non-AJAX enabled browser:
After clicking on the "view news" link with AJAX enabled:
If you notice the URLs in the second and third screen shots, you'll see that with AJAX disabled the browser simply navigated to where the link was pointing. Thus, a graceful degradation was achieved.
With little effort, we achieved an AJAX enabled ASP.NET MVC site, and cleanly/gracefully allowed non-AJAX users to enjoy the same benefits of our demo app. The project was written in Visual Studio 2008 SP1 with the ASP.NET MVC Beta 1 bits installed. Because the DLL's are bin-deployed, you should be able to download and run the project even if you don't have the MVC beta install. Check it out for yourself: SingingEels_MvcAjaxMashup.zip