Mobile support in MVC 3
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):
- 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).
- 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).
- 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.