Mobile Web Application Using MVC - Part1

Download Sample Project

Today Visual Studio 2012 became available for download on MSDN. Mobile development is one of the hot topics of development using new development environment. This post is along the same lines. In this post I will discuss some basics of how you MVC4 helps you in developing web applications for mobile devices.

Developing a web application for Mobile devices is no different than developing for desktop. The only difference is presenting the data to the user in a smaller view. So in a nutshell you are looking for an intuitive and easier way to switch views of your MVC application based on device that is accessing your web application. MVC4 makes this process very transparent and easy to implement.

Before I go into implementation details, lets take one simple example. In your application you will have some Home controller and this controller has some default view Index. When your accesses your application, you load this Index view for this user. Now you have another user who accesses your application using a mobile phone (iPhone, Android, Windows 8 etc.). Now you would want your MVC application to load view that will fit on this phone and follows some standard mobile device usability paradigm. Intuitively you would like underlying framework to detect that user is using a mobile device and load some view like Index.MobileDevice or something along those lines. MVC4 framework does exactly this with little help from you in detection of device.

DisplayModeProvider

MVC4 framework provides necessary plumbing by using DisplayModeProvider. If you look at implementation of this class, you will find that this has collection of IDisplayMode objects that provide MVC4 framework information about what all display mode our application knows about and how to detect them. There are two static properties in this class that provide some hint about how MVC framework handles mobile devices transparently.

public static readonly string DefaultDisplayModeId = string.Empty;
public static readonly string MobileDisplayModeId = "Mobile";
    

Now it us look at constructor of this class.

internal DisplayModeProvider()
{
   List<IDisplayMode> list = new List<IDisplayMode>();
   DefaultDisplayMode item = new DefaultDisplayMode(MobileDisplayModeId) {
     ContextCondition = context => context.GetOverriddenBrowser().IsMobileDevice
   };
   list.Add(item);
   list.Add(new DefaultDisplayMode());
   this._displayModes = list;
}
    

What this code means is that MVC4 framework has a display mode that is capable of detecting mobile devices by using some condition. This detection is done by a Func assigned to ContextCondition property of DefaultDisplayMode object. What this implementation does is that if MVC detects that user is using a Mobile device, it will look for a view that has name with format {viewname}.Mobile.cshtml. The critical part of this name is string Mobile that was set into DisplayModeId property of IDisplayMode interface. You get the idea that if you create view with this DisplayModeId string suffix, MVC framework will automatically load that view. So for the example that we started to discuss, if we create a view named Index.Mobile.cshtml, we have accomplished the mission.

Mobile does not cover all

This default mobile display mode provided by framework works for most part. But it falls short if you have provide device specific view. Definition of Mobile is very wide. It covers phones, tablets, etc. And then tablets have small and big screens. If you are using 10.1in tablets then you definitely want to take advantage of larger view instead of using a view for a phone. This means you will need to add some more display modes into your application.

Handling Tablets and Phones in MVC application

To accomplish detection of individual device classes, you will need to do following steps.

  • Add display mode objects that implements IDisplayMode interface. For most part DefaultDisplayMode class will do the job for you.
  • Come up with a DisplayModeId suffix that you will use for your view types
  • Provide a Func that will help in detection of device
  • Insert this DefaultDisplayMode objects into the existing collection of MVC

Detect Phones and Tablets

I have implemented a simple extension class that helps in providing a very quick detection of tablet and phone devices.

public static class BrowserDetector
{
  static string[] TabletAgents = new string[] { 
        "iPad", "Transformer", "Asus-Galaxy", 
        "Samsung Galaxy Tab", "Galaxy Nexus" };
  static string[] PhoneAgents = new string[] 
        { "iPhone", "iPod", "Samsung-Sgh", "BlackBerry", 
        "XT720", "Razor", "DroidX", "Droid X", "Htc Wildfire", 
        "Lumia", "HTC Sensation", "HTCSensation", "HTC_Sensation" };
  public static bool IsMobilePhone(this HttpContextBase context)
  {
    var agent = context.GetOverriddenUserAgent();
    bool phone = !string.IsNullOrEmpty(Array.Find(
        PhoneAgents, pa => agent.IndexOf(pa, StringComparison.OrdinalIgnoreCase) >= 0));
    return phone;
  }

  public static bool IsTablet(this HttpContextBase context)
  {
   var agent = context.GetOverriddenUserAgent();
   bool tablet = !string.IsNullOrEmpty(Array.Find(
        TabletAgents, pa => agent.IndexOf(pa, StringComparison.OrdinalIgnoreCase) >= 0));
   return tablet;
  }
}
    

The static functions are just looking for existence of well established anchors in user agent strings used by mobile device browsers. You can add more strings in PhoneAgents and TableAgents collections.

Add display modes

Following implementation shows how display modes are added at application load time.

In Global.asax.cs

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    DisplayModeConfig.RegisterDisplayModes(DisplayModeProvider.Instance.Modes);
}

Class encapsulating implementation
public class DisplayModeConfig
{
  public static void RegisterDisplayModes(IList<IDisplayMode> modes)
  {
   var mode = new DefaultDisplayMode("Phone")
   {
       ContextCondition = PhoneDisplayCondition
   };
   modes.Insert(0, mode);

   mode = new DefaultDisplayMode("Tablet")
   {
      ContextCondition = TabletDisplayCondition
   };
   modes.Insert(0, mode);
 }

 public static bool PhoneDisplayCondition(HttpContextBase context)
 {
   return context.IsMobilePhone();
 }

 public static bool TabletDisplayCondition(HttpContextBase context)
 {
   return context.IsTablet();
 }
}
    

Insert order matters

You will notice that new modes are being inserted at ZERO index. This is very important part of the implementation. MVC framework performs display mode detection in order of display mode objects in the list. When the first detection function returns true it stops. If you will insert your custom display modes at the end, then MVC framework will stop at its default DisplayMode that it inserted for Mobile suffix in constructor of DisplayModeProvider and your application will not be able to detect device specific browsers and load appropriate views. Therefore it is very important that you add these DefaultDisplayMode objects from most important to least important.

Demo

I have uploaded the example project, attached with this post, at m.byteblocks.com. You can try visiting this URL with different devices (iPhone, iPad, iPod, Droid, Razor etc.) and see how the page's title is different.

comments powered by Disqus

Blog Tags