dotMobimobiThinkingmobiForgemobiReadyDeviceAtlasgoMobi
background image

The DeviceAtlas API in ASP.NET- Part I (The Basics)

Section Feature Image
Posted by adrian.hopebailie - 27 Nov 2008
Twitter share icon Facebook share icon Google Plus share icon

Update - 10/02/2009

We have just released version 2.3 of our API as a Beta with a whole host of new features that make integrating it into any ASP.NET website much much easier. The download comes with extensive samples and documentation to help you get started.
Find out more...

DeviceAtlas is the world's most comprehensive database of mobile device information. The database comes with an API that developers can use to determine the capabilities of devices browsing their website and in so doing adapt their content to make it suitable for the user’s context.

Part I of this tutorial will assist ASP.NET developers in learning the basics of the API and how to use it.

A very similar tutorial is available for PHP here.

Background

In order to provide relevant content to users on mobile devices content providers are forced to adapt their content to suit the capabilities of the user's device. In order to do this the content provider must analyse the request sent by the user to try and determine what device they are actually using.

All devices, when connecting to a content provider will send a number of headers with details about the web browser being used, the character encoding they support, the MIME types they can handle and more. Unfortunately the information provided in these headers is often incomplete, inconsistent or even modified by proxies along the way so that the content provider faces an ever more complex task determining what device is trying to access their content.

The most effective clue in determining a user's device is the "User Agent" header. The DeviceAtlas API uses this header to query its extensive database of devices and to give the content provider details about any capabilities or limitations of the user's device. The provider can then be sure they are delivering content that will be accessable and usable for that specific device.

Introduction

Part I of this tutorial will introduce developers to DeviceAtlas and the DeviceAtlas API. It will demonstrate how an ASP.NET developer may use the API in delivering adapted content to their users.

DeviceAtlas simply provides the database of devices and functions to query this database with a "User Agent" string. Functionality such as caching the database and "sniffing" out the user agent string in unusual circumstances is left to the developer.

Part I of the tutorial will ignore these for now however Part II will focus on addressing those extra aspects of a DeviceAtlas implementation and make suggestions about how these tasks may be tackled.

Target

Any level of ASP.NET developer comfortable with the basics of delivering an simple ASPX page. (C# is used in this example but converting to VB or any other .NET language should be easy.)
It is suggested that users be familiar with HTML and if possible XHTML-MP and CSS.

System Requirements

To complete the tutorial you will need a web server (local or remote) running ASP.NET and .NET Framework 2.0 or later. I am using IIS7 on Windows Vista with .NET Framework 3.5. Visual Studio is NOT required to complete this tutorial, any text editor will suffice.

Time

Part I of the tutorial will take between 5 and 20 minutes depending on your level of competence with ASP.NET. Advanced developers will be able to skim over this tutorial and will most likely find the example code quite self-explanatory.

File Structure

Download the latest .NET version of the DeviceAtlas API (You will need to be logged in. Use your mobiforge account or create one. It's free!).

DeviceAtlas API Downloads

Unzip the contents into the web root of your project. As is traditional for a beginner’s tutorial I have called the project Hello World so my directory structure looks like this:

<br />        /helloworld <br />            /doc <br />                (API Documentation...)<br />            /sample<br />                /bin<br />                    DA.dll <br />                /json<br />                    Sample.json <br />                /Properties<br />                    AssemblyInfo.cs <br />                Default.aspx
                Device Atlas API Sample.csproj
                Web.config
            DA.dll<br />            Test.exe
  • doc contains the documentation for the API which is a useful reference for the functions offered by the API.
  • sample contains a basic sample C# project using the API and a developer version of the json database (Identical structure to the live data but may not be up to date.)
  • DA.dll is the API library
    Test.exe is a comand line test tool for the API.

When starting a new web project using DeviceAtlas developers using Visual Studio may find it easiest to copy the entire contents of the sample folder and use it as a base. However developers that are not using Visual Studio can still follow this tutorial to get an idea of how to start with a simple text editor.

To get started I also created a file called Default.aspx in the root and created a folder called json where I have placed a fresh new copy of DeviceAtlas.json (the downloaded from the website). The standard for ASP.NET is to have assembly files in a bin folder in the root of the application. I have created this folder and moved DA.dll into it. This requires that I tell IIS to convert helloworld to an application (do this in the IIS management console), otherwise it will never look in bin for the required assemblies.

If you encounter errors later like
    Compiler Error Message: CS0246: The type or namespace name 'Mobi' could not be found (are you missing a using directive or an assembly reference?)
then you need to check that IIS can find DA.dll.

We don't need Test.exe for the web app so I've removed it.

 so the project directory now looks like this:

<br />	/helloworld <br />            /bin<br />                DA.dll 
            /doc <br />                <i>(API Documentation files...)</i><br />            /sample<br />                <i>(Sample files...)</i><br />            /json<br />                DeviceAtlas.json 
            Default.aspx

Default.aspx is the root of the project and will load the device database from DeviceAtlas.json.

Tutorial

Step 1

We begin by editing Default.aspx.All we want for now is a basic html page that says "Hello World". So insert the following lines:

<%@ Page Language="C#" %>
<%
    Response.AddHeader("Cache-Control", "max-age=200");
    Response.AddHeader("Content-Type", "application/xhtml+xml");
%><?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"
    "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Hello Mobile World</title>
</head>
<body>
    <p>Hello Mobile World!</p>
</body>
</html>

A very basic XHTML-MP page that simply sets the page title and displays the text "Hello World". I have uploaded the project to the web and tested it on ready.mobi. In the Nokia N70 Emulator the page looks like this:

Step 1

Step 2

Not a very inspiring page so far and one that certainly won't need any changes for different screen sizes or device capabilities. But let's throw in a picture logo, some links and some styling to jazz it up a bit. The code now looks like this:

<%@ Page Language="C#" %>
<%
    Response.AddHeader("Cache-Control", "max-age=200");
    Response.AddHeader("Content-Type", "application/xhtml+xml");
%><?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" 
    "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Hello Mobile World</title>
    <style type="text/css">
        h1 { background-color: #000000; color: #ffffff;}
    	li { list-style: none;}
    </style>
</head>
<body>
    <p><img id="logo" src="img/logo_128x57.png" alt="dotMobi Logo" width="128" height="57"/></p>
    <hr />
    <h1>Hello Mobile World!</h1>
    <ul>
        <li><a href="index.php?page=1" accesskey="1">(1) Link 1</a></li>
        <li><a href="index.php?page=2" accesskey="2">(2) Link 2</a></li>
        <li><a href="index.php?page=3" accesskey="3">(3) Link 3</a></li>
    </ul>
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
    In euismod mi a urna. In ultrices turpis vitae nibh.</p>
    <p>Sed sed ipsum id dolor nonummy dignissim. Nulla mi ante, 
    placerat nec, vestibulum sed, fringilla at, velit.</p>
    <p>Nulla nonummy purus sed nisl. Mauris tincidunt urna sit amet dui. 
    Cras sem justo, mollis et, tincidunt a, pellentesque eget, quam. 
    Vestibulum quis velit et erat dictum ultrices. 
    Praesent fermentum arcu nec sapien. Nunc eleifend.</p>
</body>
</html>

And the emulator gives us:

Step 2

Not likely to win any style awards but contains many of the basic elements of a mobile web page.

Step 3

Now let's introduce DeviceAtlas. The first step is to include the API assembly and load up the database of devices into a tree which we assign to the Hashtable variable Tree. We do this by adding the following lines to the block at the top of the page.

<%@ Import Namespace="Mobi.Mtld.DA" %>
<%@ Import Namespace="Mobi.Mtld.DA.Exception" %>
<%@ Import Namespace="System.Collections" %>
<%
    Hashtable Tree = Api.GetTreeFromFile(Request.PhysicalApplicationPath + "json/DeviceAtlas.json");
%>

The next step is to get the user agent header sent by the device so we can query the database. The user agent is usually stored in the variable Request.UserAgent. This value is often inconsistent usually due to interference by proxies. There are ways to "sniff" out the correct user agent which are covered in Part II of this tutorial. For now we just assume the server variable is correct.

    string UA = Request.UserAgent;

Now all of the API functions are available to us. Let's start using them by wowing our visitor and telling them what device they are using.

I have replaced our <h1>Hello Mobile World!</h1> with the following code:

    <%
    string Vendor;
    try {
          Vendor = Api.GetProperty(Tree, UA, "vendor");
    } catch (InvalidPropertyException e) {
          Vendor = "Unknown";
    }
    %>
    <h1>Hello <%= Vendor %> user!</h1>

The result on the N70 emulator is:

Step 3

Step 4

Notice we have determined the device manufacturer by using the Api.GetProperty function of the api. If this property value is unknown we catch the InvalidPropertyException and provide a default.

But how did I know what value to put as the third argument, in this case vendor?

The beauty of the DeviceAtlas database is that it is constantly evolving. Over time we plan to increase the number of characteristics that are included for each device so it is impossible to publish a list of these properties that will be valid for all time.

The easiest way to get a list of available properties is to use the function Api.ListProperties. This will return an array of all the properties stored in your current version of the DeviceAtlas data. The latest version has a property called vendor which will contains the name of the device vendor.

Another useful function is Api.GetProperties which will return a Hashtable of all the properties available for this device. The array is indexed by the property names. For more info on the properties and functions in the API have a look at the API documentation that comes as part of the API download.

In the next snippet I have replaced the links and paragraphs with some new code to loop through the properties and display them on screen:

<%@ Page Language="C#" %>
<%@ Import Namespace="Mobi.Mtld.DA" %>
<%@ Import Namespace="Mobi.Mtld.DA.Exception" %>
<%@ Import Namespace="System.Collections" %>
<%
    Hashtable Tree = Api.GetTreeFromFile(Request.PhysicalApplicationPath + "json/DeviceAtlas.json");
    string UA = Request.UserAgent;
 
    Response.AddHeader("Cache-Control", "max-age=200");
    Response.AddHeader("Content-Type", "application/xhtml+xml");
%><?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" 
    "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Hello Mobile World</title>
    <style type="text/css">
        h1 { background-color: #000000; color: #ffffff;}
    	li { list-style: none;}
    </style>
</head>
<body>
    <p><img id="Img1" src="img/logo_128x57.png" alt="dotMobi Logo" width="128" height="57"/></p>
    <hr />
    <%
    string Vendor;
    try {
          Vendor = Api.GetProperty(Tree, UA, "vendor");
    } catch (InvalidPropertyException e) {
          Vendor = "Unknown";
    }
    %>
    <h1>Hello <%= Vendor %> user!</h1>
    <ul>
    <% foreach(DictionaryEntry entry in Api.GetProperties(Tree, UA) ){ %>
         <li><span class="property"><%= entry.Key.ToString() %>: </span><%= entry.Value.ToString() %></li>
    <% } %>
    </ul>
        </body>
</html>

The output is not very pretty but it gives you an idea of what DeviceAtlas can tell us about the device that is browsing our site.

Step 5

Step 5

Finally Let's get back to our code from Step 3 and make some changes so that we can adjust our output dependant on the user's device capabilities. A slightly more practical use for DeviceAtlas than merely telling the user what device they are using!

Let's assume that our existing design will work for mid-range browsers. What about high end browsers like an iPhone or really low end browsers without image support?

First I will test for PNG support and decide if we want to display our image at all. Next I will check to see if the device screen is wide enough to use a bigger image. The resulting code looks like this:

<%@ Page Language="C#" %>
<%@ Import Namespace="Mobi.Mtld.DA" %>
<%@ Import Namespace="Mobi.Mtld.DA.Exception" %>
<%@ Import Namespace="System.Collections" %>
<%
    Hashtable Tree = Api.GetTreeFromFile(Request.PhysicalApplicationPath + "json/DeviceAtlas.json");
    string UA = Request.UserAgent;
 
    Response.AddHeader("Cache-Control", "max-age=200");
    Response.AddHeader("Content-Type", "application/xhtml+xml");
 
%><?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" 
    "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Hello Mobile World</title>
    <style type="text/css">
        h1 { background-color: #000000; color: #ffffff;}
    	li { list-style: none;}
    </style>
</head>
<body>
    <%
        bool PngSupport;
        int DisplayWidth, ImageWidth, ImageHeight;
        string ImagePath;
        try{
            PngSupport =  Api.GetPropertyAsBoolean(Tree, UA, "image.Png");
        } catch (InvalidPropertyException e) {
            PngSupport = false; //You may wish to have some other fallback (like assuming true for unknown)
        }
        if(PngSupport){ //Supports PNG images
 
            try{
                DisplayWidth = Api.GetPropertyAsInteger(Tree, UA, "image.Png");
            } catch (InvalidPropertyException e) {
                DisplayWidth = 128; //Default to 128 for unknown
            }
            if(DisplayWidth >= 240){
                ImagePath = "logo_239x107.png";
                ImageWidth = 239;
                ImageHeight = 107;
            } else {
       		    ImagePath = "logo_128x57.png";
                ImageWidth = 128;
                ImageHeight = 57;
            }
    %>
    <p><img id="Img2" src="img/<%= ImagePath %>" 
          alt="dotMobi Logo" width="<%= ImageWidth %>" 
          height="<%= ImageHeight %>"/></p>
    <%   } %>
    <hr />
    <%
    string Vendor;
    try {
          Vendor = Api.GetProperty(Tree, UA, "vendor");
    } catch (InvalidPropertyException e) {
          Vendor = "Unknown";
    }
    %>
    <h1>Hello <%= Vendor %> user!</h1>
    <ul>
        <li><a href="index.php?page=1" accesskey="1">(1) Link 1</a></li>
        <li><a href="index.php?page=2" accesskey="2">(2) Link 2</a></li>
        <li><a href="index.php?page=3" accesskey="3">(3) Link 3</a></li>
    </ul>
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
    In euismod mi a urna. In ultrices turpis vitae nibh.</p>
    <p>Sed sed ipsum id dolor nonummy dignissim. Nulla mi ante, 
    placerat nec, vestibulum sed, fringilla at, velit.</p>
    <p>Nulla nonummy purus sed nisl. Mauris tincidunt urna sit amet dui. 
    Cras sem justo, mollis et, tincidunt a, pellentesque eget, quam. 
    Vestibulum quis velit et erat dictum ultrices. 
    Praesent fermentum arcu nec sapien. Nunc eleifend.</p>
</body>
</html>

The output won't change when viewed on the emulator but if a user browsed this page from an older phone that couldn't display PNG images I would exclude the image from my output altogether. Also if I am fortunate and the user has a nice big display I know I can take advantage of this and use a bigger image rather than have my image lost in the corner of the screen.

What this very basic example demonstrates is how a developer may use DeviceAtlas to access the characteristics of a device and use these to determine how they choose to adapt their output.

The example above is extremly simplified and it is left to the developer to decide the best way to implement the DeviceAtlas API. The amount of content to adapt, the target audience and the specific needs of the website should all be considered in developing a content adaption strategy.

Tools like ready.mobi will help you to test your site as they simulate the headers of the phone they are emulating.

In Part II of the tutorial we will look at caching device data for better performance and "sniffing" out the correct user agent before querying the DeviceAtlas API to ensure more accurate results.

Part II coming soon...


Posted by adrian.hopebailie - 27 Nov 2008

adrian.hopebailie's picture

Member of the dotMobi Technical team

Posted by stylz 4 years ago

Thanks for this!!

Posted by StantonR 4 years ago

Hi There

I followed your basic tutorial and I am still not getting a 4 Rating in Mobi.Ready.
I get the following errors
Your page does not use XHTML Mobile Profile
Your page markup does not validate

You can try the following url in mobi.ready

http://dev.webnow.co.za/liberty.mobi

It get a 4 rating and renders in most browsers but I would like to try and get a 5 rating before creating my mobi site.

Your help would be appreciated.