Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Abstracting, Caching, and Sharing WURFL

0.00/5 (No votes)
7 Feb 2009 5  
Simple and easy mobile device capability queries in ASP.NET.

Download solution

WURFL2_file_sequence2.png

Introduction

In a previous article (WURFL ASP.NET Implementations) I presented a comparison of 3 ASP.NET WURFL libraries for querying the capabilities of mobile devices. This current article takes one of the implementations (WURFL.Marg) which proved the best performer, and creates a wrapper class for it. The library (class) exposes consistent high level objects, creates an object hierarchy (as opposed to a flat collection of type string), caches the objects with a dependency on the data file, and shares this data across many web-applications.

Background

The decision to create a wrapper class rather than extend the existing source files was based on loose coupling.

  • If the source for WURFL.Marg is altered by the maintenance developers, as long as the used method signatures are not altered, this wrapper class should still function correctly, with minor alterations.
  • The wrapper class is not implementation specific - if another WURFL library is chosen instead of WURFL.Marg then the cutover will be quite simple.

Sharing the data files is not such a big deal is it? Well yes and no. It is supported out of the box with WURFL.Marg but caching isn't. Once dependency-centric caching is provided, special consideration is needed for the shared location of the data file (WURFL.xml - the device capability data).

The caching itself is not complex - the object heirachy needs to be considered, and a reload of the cache is needed when the data file is modified. This is acheived using the System.Web.Caching.Cache class, setting a CacheDependency object for the WURFL.xml file and using a deffered event via the CacheItemRemovedCallback class for reloading the cache once the data file has been modified.

The same metrics were applied for the wrapper class as were applied to the three WURFL implementations in the previous article. The Tests steps were:

  1. user agent: current device
    capability: mobile_browser
    data modified: false
  2. user agent: current device
    capability: xhtml_table_support
    data modified: false
  3. user agent: current device
    capability: ajax_support_javascript
    data modified: false
  4. user agent: current device
    capability: resolution_width
    data modified: false
  5. user agent: NokiaN92-2
    capability: mobile_browser
    data modified: false
  6. user agent: NokiaN92-2
    capability: xhtml_table_support
    data modified: false
  7. user agent: NokiaN92-2
    capability: ajax_support_javascript
    data modified: false
  8. user agent: NokiaN92-2
    capability: resolution_width
    data modified: false
  9. user agent: iPhone
    capability: mobile_browser
    data modified: true

The results were:

WURFL2_metrics_600x97.png

The wrapper class was tested with the strongly typed hierarchy of capabilities (including intellisense) and without those properties. The differences were negligible; the strongly typed capabilities did not prove a performance hit. The differences in tests #1 & #5 can be attributed to the cache being loaded and is worth the "hit". The obvious difference is in test #9 - this is a desirable result. This indicates that as the data file is modified on the server, the cache was being reloaded; this did not happen with any of the previous WURFL implementations tested.

The following diagram shows the hierarchy of capabilities and the supporting intellisense:

WURFL2_intellisense2.png

Using the code

Both WURFL.Marg and emx.tcp.mobile are used and they will be needed to be added as a reference to the Web Application/Website project. log4net will be added to the bin as a dependency (of WURFL.Marg) and is not necessary as a reference.

The web.config file will need the base WURFL.Marg edits listed below:

WURFL2_web_config.png

The log4net and browserCaps sections are optional.

The uses of the shared methods are very simple. The querying of capabilities of the current device using the original flat collection and the strongly typed object is:

// flat WurflDeviceIndex collection
Response.Write(
emx.tcp.mobile.Device.currentDevice()
.capabilities["resolution_height"].value + "<br/>");


// strongly typed equivilent object
Response.Write(
emx.tcp.mobile.Device.currentDevice()
.display.resolutionHeight + "<br/>");

The querying of capabilities of a referred device (with user-agent) using the original flat collection and the strongly typed object is:

// flat WurflDeviceIndex collection
Response.Write(
emx.tcp.mobile.Device.referredDevice("NokiaN92-2")
.capabilities["resolution_height"].value + "<br/>");


// strongly typed equivilent object
Response.Write(
emx.tcp.mobile.Device.referredDevice("NokiaN92-2")
.display.resolutionHeight + "<br/>");

All the caching and object instantiation is performed in the background - simple and easy...

Points of Interest

Unfortunately the the referredDevice object has full Caching/Dependency awareness and the currentDevice hasn't. The currentDevice instantiation took (indirectly) the user-agent as a parameter - so, in practical terms, its only good for the length of the session. Therefore the currentDevice is stored in the Session dictionary. A new method has been added (loadCurrentCache) which can be called from the SessionStart event.

Future Enhancements

I am adding some logging (user-agent, application etc) code for my current project, and intend to mine that to cache and index the most widely used user-agents - if this process is modular enough I will add it to this library...

History

  • 2009-02-09 - currentDevice stored in Session dictionary
  • 2009-02-07 - Article submitted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here