Skip to content

Mobile support in MVC 3

May 24, 2012

Given that I just did a webcast on mobile support in MVC 4, I thought it fitting to discuss how essentially the same mobile support can be achieved today in MVC 3. In a fairly simple way we can build a similar framework to what will be provided in the next version.

I want these requirements (which are comparable to what we get in MVC 4):

  1. I don’t want a controller action to have to fret about what view to deliver based upon the client device (mobile vs. non-mobile).
  2. I want a mobile view to be delivered if there is a view that conforms to a particular naming convention (such as Index.Mobile.cshtml).
  3. I only want a render the mobile view if the client device is a mobile device (this one is sort obvious).

To alleviate the controller of the logic to decide if a mobile view should be rendered or not we will develop an action filter. This allows common functionality to extracted into one location yet applied to multiple controllers and actions.

To dynamically discover if we have a mobile version of a view we’ll have to ask the MVC plumbing a few questions, but it’s not difficult.

To know if the current request is from a mobile device, we’ll simply ask ASP.NET :)

Here’s the action filter:

public class MobileAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        // is the request a view and is the client device a mobile device
        var vr = filterContext.Result as ViewResult;
        if (vr != null &&
            filterContext.HttpContext.Request.Browser.IsMobileDevice)
        {
            // determine from the current view what the mobile view name would be
            var viewName = vr.ViewName;
            if (String.IsNullOrWhiteSpace(viewName)) viewName = (string)filterContext.RouteData.Values["action"];
            var fileExtension = Path.GetExtension(viewName);
            var mobileViewName = Path.ChangeExtension(viewName, "Mobile" + fileExtension);

            // ask MVC is we have that view
            var ver = ViewEngines.Engines.FindView(filterContext, mobileViewName, vr.MasterName);
            if (ver != null && ver.View != null)
            {
                ver.ViewEngine.ReleaseView(filterContext, ver.View);

                // we do, so tell MVC to use the mobile view instead
                vr.ViewName = mobileViewName;
            }
        }
    }
}

And here’s the action filter applied to a controller:

[Mobile]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

Of course, this could also be applied globally in the MVC application.

So this shows: 1) How easy it is to have mobile support in MVC versions prior to MVC4, and 2) How powerful action filters are at providing interception into the MVC framework.

Sample code here.

No comments yet

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: