Linking 51Degrees Device Detection Repository to MVC Views
Being able to tell if a web page is being viewed from a web enabled television, a phone, tablet or even something completely different, like a screen reader has profound implications on what kind of content should be served. For example; advertising positioning and format will change, business process will be altered based on likely input methods, and light weight UIs produced for bandwidth constrained devices.
Feature detection and CSS queries are becoming more accepted and more available everyday, and while they certainly have their uses, there're still many devices lacking support and which adds a layer of complexity to your web application.
If you could easily tell what type device was on your site, your server can make intelligent decisions about what content, scripts, and styles to send without you needing to worry about cross browser support for every part of your web application. This blog post shows how easy it is to address these issues with the new features of Microsoft MVC5.
Installing
The first step is to install 51Degrees into your project. For this I am using a new Visual Studio 2013 MVC 5 project, but this should work for any version of MVC and Visual Studio as long as the project is using .NET 4 or above. In the Nuget package manager search for 51Degrees and install. This package comes with an aspx test page that we don't need, so 'Mobile/Default.aspx' can be deleted.
And that's it for installing! All configuration is administered in 51Degrees.config. You should remove the redirect element in that file as redirection doesn't fit very well in MVC as controllers cannot be reused. Redirection is useful when dealing with Web Forms projects.
Linking Device Data to Views
It is now time to link some device information to the view. I will make a model class that holds device data that will ultimately get passed to the view, and a base controller class that creates a model containing device data which is then passed into the ViewBag.
The model class, which I'll simply call 'Device', takes a 51Degrees 'Match' object in its constructor. It then uses reflection to see which properties the Device object has and looks for a 51Degrees property with the same name. This means that to get a new property for your View you only need to add a new property to Device supporting very quick prototyping.
using FiftyOne.Foundation.Mobile.Detection;
using System.Linq;
namespace FiftyoneDegreesMVC.Models
{
public class Device
{
// These properties are populated in the constructor with
// 51Degrees properties of the same name. More can be added
// as long as their name is the same as the 51Degrees
// property and they have the same type. More properties
// are listed at /Resources/Property-Dictionary
public bool IsMobile { get; private set; }
public string HardwareVendor { get; private set; }
public string HardwareModel { get; private set; }
public string PlatformVendor { get; private set; }
public string PlatformName { get; private set; }
public string PlatformVersion { get; private set; }
public string BrowserVendor { get; private set; }
public string BrowserName { get; private set; }
public string BrowserVersion { get; private set; }
public int ScreenPixelsHeight{ get; private set; }
public int ScreenPixelsWidth { get; private set; }
internal Device(Match match)
{
// Uses reflection to see if there is a 51Degrees property with
// the same name as a Device class property. This means getting
// a new 51Degrees property in this object only requires creating
// a property with that name. This could be hardcoded later.
var values = match.Profiles.SelectMany(p => p.Values).ToArray();
foreach(var property in this.GetType().GetProperties())
{
var value = values.FirstOrDefault(v => v.Property.Name == property.Name);
if(value != null)
{
object result = null;
if(property.PropertyType == typeof(bool))
{
result = value.ToBool();
}
else if(property.PropertyType == typeof(int))
{
result = (int)value.ToDouble();
}
else if(property.PropertyType == typeof(double))
{
result = value.ToDouble();
}
else if(property.PropertyType == typeof(string))
{
result = value.Name;
}
if(result != null)
{
property.SetValue(this, result);
}
}
}
}
}
}
A Device class can be invoked by doing the following:
Device match = WebProvider.ActiveProvider.Match(requestContext.HttpContext.Request.Headers);
Now we need a controller to create a Device. Controllers could create their own Device but for better code reuse I'll be making a base controller. It will create the Device by overriding the Initialize method.
using FiftyOne.Foundation.Mobile.Detection;
using FiftyoneDegreesMVC.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace FiftyoneDegreesMVC.Controllers
{
public abstract class BaseController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
// get a match from 51Degrees and use it to create a Device object.
var match = WebProvider.ActiveProvider.Match(requestContext.HttpContext.Request.Headers);
ViewBag.Device = new Device(match);
}
}
}
All views from a controller extending BaseController can now use ViewBag.Device:
<div>
<!-- The Device object is created by BaseController -->
<h2>Device Info</h2>
<p>
These properties are filled with 51Degrees Device Data. If a value is missing it is likely not to be in the
current data file and you should try with Premium or Enterprise data.
</p>
<div>IsMobile: @ViewBag.Device.IsMobile</div>
<div>HardwareVendor: @ViewBag.Device.HardwareVendor</div>
<div>HardwareModel: @ViewBag.Device.HardwareModel</div>
<div>PlatformVendor: @ViewBag.Device.PlatformVendor</div>
<div>PlatformName: @ViewBag.Device.PlatformName</div>
<div>PlatformVersion: @ViewBag.Device.PlatformVersion</div>
<div>BrowserVendor: @ViewBag.Device.BrowserVendor</div>
<div>BrowserName: @ViewBag.Device.BrowserName</div>
<div>BrowserVersion: @ViewBag.Device.BrowserVersion</div>
<div>ScreenPixelsWidth: @ViewBag.Device.ScreenPixelsWidth</div>
<div>ScreenPixelsHeight: @ViewBag.Device.ScreenPixelsHeight</div>
</div>
Example MVC5 Mobile Output
You should now be able to navigate to this page and see information about your device displayed. If you're using a desktop browser then the information returned will be limited. Either use the device emulation capabilities of the web browser to pretent to be a mobile or tablet, or if you've connected to the same network a real device.
Missing Values - Enhanced Device Data
Some of the properties won't be populated unless Premium or Enterprise device data is used with 51Degrees. A full list of properties and the data sets they are contained in is available here. To evaluate either Premium or Enterprise data please fill in the following form and we'll provide the relevant data file.
Conclusion
This is just a simple example but this information could be used in your view to move content around, use different CSS, change some Javascript parameters or serve different images. This allows better control over your website and what your users see without having to worry about testing every change on every platform and if a certain piece of Javascript or CSS is widely supported.
A full example of this is available for download.
For more MVC goodness with 51Degrees, see our MVC documentation page.