Check out the latest documentation.

Example Web Site

The main C download includes an example IIS .NET web site ready to run from within Visual Studio 2010 or greater. It includes the following:

  • Dynamic Link Library (DLL) projects for the Pattern and Trie methods exposing required methods suitable for calling from Common Language Runtime.
  • An inter operation wrapper for the two methods exposing functionality via .NET classes. This layer avoids having to make DLL calls directly from your code.
  • A simple web site with one page to display properties using both methods for the requesting browser.

Start by opening the FiftyOne.Mobile.Detection.Provider.sln solution from within the windows folder. Open the Demo web project and locate the Default.aspx.cs file. Change the following line so that it points to the location of your Trie data file.

													1
													
														
														private
														
														
														const
														
														
														string
														
													 TRIE_DATA_FILE = 
														
														"..\\..\\51Degrees.com.data.dat"
														
													;

													

The web site will run within IIS Express and can be started without further changes. Initial compilation may take 5 to 10 minutes as the Pattern DLL is generated. The initial page of the web site when displayed in Chrome emulating a Nexus S should be similar to the following.

Web Page

The Default.aspx.cs page contains the code which creates detection providers, and calls them to determine properties for the device. The following code is relevant.

													 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
													
														
														private
														
														
														const
														
														
														string
														
													 TRIE_DATA_FILE = 
														
														"..\\..\\51Degrees.com.data.dat"
														
													;

        
														
														// Initialise the pattern provider with a list of 4 properties.
														
														
														private
														
														
														static
														
														
														readonly
														
													 PatternWrapper _pattern = 
														
														new
														
													 PatternWrapper(
														
														new
														
													[] {
                
														
														"Id"
														
													, 
														
														"IsMobile"
														
													, 
														
														"ScreenPixelsWidth"
														
													, 
														
														"ScreenPixelsHeight"
														
													 });

        
														
														// Initialise the tree provider with a data file and a list of 4 properties.
														
														
														private
														
														
														static
														
														
														readonly
														
													 TrieWrapper _trie = 
														
														new
														
													 TrieWrapper(
            Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TRIE_DATA_FILE),
            
														
														new
														
													[] { 
														
														"Id"
														
													, 
														
														"IsMobile"
														
													, 
														
														"ScreenPixelsWidth"
														
													, 
														
														"ScreenPixelsHeight"
														
													 });

        
														
														// IMPORTANT: For a full list of properties see: 
														
														
														// http://51degrees.mobi/products/devicedata/propertydictionary
														
														
														protected
														
														
														void
														
														
														Page_Init
														
													(
														
														object
														
													 sender, EventArgs e)
        {
            
														
														// Get properties for the current useragent.
														
														
														var
														
													 patternProperties = _pattern.GetProperties(Request.UserAgent);
            
														
														var
														
													 trieProperties = _trie.GetProperties(Request.UserAgent);

            
														
														// Output the properties from each provider.
														
														
														var
														
													 builder = 
														
														new
														
													 StringBuilder();
            builder.Append(
														
														"<table>"
														
													);
            builder.Append(
														
														"<tr><th></th><th>Pattern</th><th>Trie</th></tr>"
														
													);
            
														
														foreach
														
													 (
														
														var
														
													 property 
														
														in
														
													 patternProperties)
            {
                builder.Append(
														
														"<tr>"
														
													);
                builder.Append(String.Format(
                    
														
														"<td><b>{0}</b></td>"
														
													,
                    property.Key));
                builder.Append(String.Format(
                    
														
														"<td>{0}</td>"
														
													,
                    String.Join(
														
														","
														
													, property.Value)));

                
														
														// Add the tree property if one exists.
														
														
														if
														
													 (trieProperties.ContainsKey(property.Key))
                    builder.Append(String.Format(
                        
														
														"<td>{0}</td>"
														
													,
                        String.Join(
														
														","
														
													, trieProperties[property.Key])));
                
														
														else
														
													
                    builder.Append(
														
														"<td></td>"
														
													);
                builder.Append(
														
														"</tr>"
														
													);
            }
            builder.Append(
														
														"</table>"
														
													);

            Results.Text = builder.ToString();
        }

													

The following lines warrant a little extra explanation.

Line 4 and 5 construct a Pattern provider initialised to return the 4 properties Id , IsMobile , ScreenPixelsWidth and ScreenPixelsHeight . Notice the provider is static so that it can be shared across multiple instances of the page. If the provider were required on many pages then it would be better to place it in a static class, or in the global.asax file.

Lines 8 to 10 construct a Trie provider. The constructor is the similar to the Pattern provider but also requires the location of the Trie data file.

Line 18 calls the GetProperties method of the Pattern provider to return a List where the key is the property string used at construction and the value is a list of values for the property. Most properties return only one value in the list, however some like CcppAccept may return many. See the Property Dictionary for more information.

Line 19 returns a List in the same structure as line 18 using the Trie provider as it's data source.

The remaining lines then produce a HTML table to display the property values returned for each provider. Line 33 joins the list of values into a single comma separated string.

Interop

The FiftyOne.Mobile.Detection.Provider.Interop.csproj project contains the wrapper classes used to call the native DLLs from CLR managed code. They handle all the complexity associated with multi-threading, initialising the DLL and freeing memory when the wrapper instance is destroyed.

This example shows them being used in a web site, but they could equally be used for offline analysis or as part of a web service.

The main advantage using the Interop layer with the Pattern matching method has over our entirely native .NET implementation is lower memory use as all the working data is compiled into the DLL as ASCII strings. The matching performance is also marginally faster.

If performance is essential and memory consumption not a factor the Trie matching method is the best solution.

Importantly these solutions will only work in a .NET application or web site configured with full trust.


Common Challenges

64 Bit & Trie

Most 32 bit systems we've tested with can not allocate more than 2 GB of continuous memory. If the Trie format data file is larger than 2 GB (Premium version) then it can not be loaded into a 32 bit application. Therefore 64 bit will need to be used.

When using a 64 bit configuration with IIS either IIS Express 8 or above will need to be installed, or a full version of IIS 7 or above will be required. If an error message similar to the following is displayed after the web site is loaded "Could not load file or assembly … An attempt was made to load a program with an incorrect format (System.BadImageFormatException)" the most likely cause will be trying to run 64 bit DLLs in a 32 bit IIS.

IIS 32 bit & 64 bit

The default demonstration web site solution compiles in 32 bit and is configured to start in IIS Express. If the configuration is changed to 64 bit IIS Express 7 can not be used as it does not support 64 bit executable. Therefore the option to use IIS Express (or the Cassini development server) is removed and the local IIS machine will need to be used. When moving to local IIS ensure that the Application Pools identity has sufficient privileges to read from the web site folder, and also if used the trie format data file.