Aug 19, 2012

ASP.NET MVC 4 Display Mode For Mobile, Tablet And TV

ASP.NET MVC 4 introduces Display Modes allows you to implement device or browser-specific views means you can target specific devices and provide device friendly interface. In this post, you will see how to implement mobile, tablet and TV specific views.

Lets first understand how to define display mode in the Application_Start method of the Global.asax, like so:


    DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
    {
      ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
        ("iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
    });

Here we defined iPhone in DefaultDisplayMode argument which defines the suffix of the view and defined condition if user agent has iPhone. When an iPhone browser is making the request(It has iPhone in user agent string), ASP.NET MVC look first for views matching the suffix "iPhone" and renders [view].iPhone.cshtml.

You might want to create different views of your app for desktop, TV(for GoogleTV, Internet.TV...etc), tablets(for ipad, kindle..etc) and mobiles. To implement this, I've added four views to home folder:

files

Read also: Responsive Design: Make Your Website Mobile, Tablet, Desktop Compatible

Tablet and TV Views:

Our objective is to create a common view for all tablets. So, we need to detect whether the device is tablet. You would use Request.Browser["IsTablet"] == "True" with 51degrees.mobi premium data. This property is NOT included in the free Lite data set.

So, I converted Categorizr(A device detection script) into C#.


 public string GetDeviceType(string ua)
        {
            string ret = "";
            // Check if user agent is a smart TV - http://goo.gl/FocDk
            if (Regex.IsMatch(ua, @"GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML", RegexOptions.IgnoreCase))
            {
                ret = "tv";
            }
            // Check if user agent is a TV Based Gaming Console
            else if (Regex.IsMatch(ua, "Xbox|PLAYSTATION.3|Wii", RegexOptions.IgnoreCase))
            {
                ret = "tv";
            }
            // Check if user agent is a Tablet
            else if ((Regex.IsMatch(ua, "iP(a|ro)d", RegexOptions.IgnoreCase) || (Regex.IsMatch(ua, "tablet", RegexOptions.IgnoreCase)) && (!Regex.IsMatch(ua, "RX-34", RegexOptions.IgnoreCase)) || (Regex.IsMatch(ua, "FOLIO", RegexOptions.IgnoreCase))))
            {
                ret = "tablet";
            }
            // Check if user agent is an Android Tablet
            else if ((Regex.IsMatch(ua, "Linux", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, "Android", RegexOptions.IgnoreCase)) && (!Regex.IsMatch(ua, "Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945", RegexOptions.IgnoreCase)))
            {
                ret = "tablet";
            }
            // Check if user agent is a Kindle or Kindle Fire
            else if ((Regex.IsMatch(ua, "Kindle", RegexOptions.IgnoreCase)) || (Regex.IsMatch(ua, "Mac.OS", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, "Silk", RegexOptions.IgnoreCase)))
            {
                ret = "tablet";
            }
            // Check if user agent is a pre Android 3.0 Tablet
            else if ((Regex.IsMatch(ua, @"GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|\\_Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook", RegexOptions.IgnoreCase)) || (Regex.IsMatch(ua, "MB511", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, "RUTEM", RegexOptions.IgnoreCase)))
            {
                ret = "tablet";
            }
            // Check if user agent is unique Mobile User Agent
            else if ((Regex.IsMatch(ua, "BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder", RegexOptions.IgnoreCase)))
            {
                ret = "mobile";
            }
            // Check if user agent is an odd Opera User Agent - http://goo.gl/nK90K
            else if ((Regex.IsMatch(ua, "Opera", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, "Windows.NT.5", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, @"HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9", RegexOptions.IgnoreCase)))
            {
                ret = "mobile";
            }
            // Check if user agent is Windows Desktop
            else if ((Regex.IsMatch(ua, "Windows.(NT|XP|ME|9)")) && (!Regex.IsMatch(ua, "Phone", RegexOptions.IgnoreCase)) || (Regex.IsMatch(ua, "Win(9|.9|NT)", RegexOptions.IgnoreCase)))
            {
                ret = "desktop";
            }
            // Check if agent is Mac Desktop
            else if ((Regex.IsMatch(ua, "Macintosh|PowerPC", RegexOptions.IgnoreCase)) && (!Regex.IsMatch(ua, "Silk", RegexOptions.IgnoreCase)))
            {
                ret = "desktop";
            }
            // Check if user agent is a Linux Desktop
            else if ((Regex.IsMatch(ua, "Linux", RegexOptions.IgnoreCase)) && (Regex.IsMatch(ua, "X11", RegexOptions.IgnoreCase)))
            {
                ret = "desktop";
            }
            // Check if user agent is a Solaris, SunOS, BSD Desktop
            else if ((Regex.IsMatch(ua, "Solaris|SunOS|BSD", RegexOptions.IgnoreCase)))
            {
                ret = "desktop";
            }
            // Check if user agent is a Desktop BOT/Crawler/Spider
            else if ((Regex.IsMatch(ua, "Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye", RegexOptions.IgnoreCase)) && (!Regex.IsMatch(ua, "Mobile", RegexOptions.IgnoreCase)))
            {
                ret = "desktop";
            }
            // Otherwise assume it is a Mobile Device
            else
            {
                ret = "mobile";
            }
            return ret;
        }

To add display mode for tablet and TV:


  DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("tablet")
            {
                ContextCondition = (context => GetDeviceType(context.GetOverriddenUserAgent()) == "tablet")
            });

            DisplayModeProvider.Instance.Modes.Insert(1, new DefaultDisplayMode("tv")
            {
                ContextCondition = (context => GetDeviceType(context.GetOverriddenUserAgent()) == "tv")
            }); 

Note: If multiple context conditions are satisfied then app will render which appears in Display Mode order first means 0 index will have the highest priority.

Mobile View:

For mobile, If you are thinking to do something like this:


 DisplayModeProvider.Instance.Modes.Insert(2, new DefaultDisplayMode("mobile")
            {
                ContextCondition = (context => GetDeviceType(context.GetOverriddenUserAgent()) == "mobile")
            }); 

OR


DisplayModeProvider.Instance.Modes.Insert(2, new DefaultDisplayMode("Mobile")
            {
                ContextCondition = (context => context.Request.Browser.IsMobileDevice)
            });

NO NEED to do it, mobile suffix is already inbuilt for mobile devices. By default, if you add a .mobile.cshtml view to a folder, that view will be rendered by mobile devices.

if no condition matches for any defined display mode, default desktop view is displayed.

You can test it using Mozilla User Agent Switcher Add-on.

desktopmobiletabletTV

Hope, It helps. Share your opinion or suggestion how you are implementing cross device web app.