From the Cloud with Love and Only the User Agent String

From the Cloud with Love and Only the User Agent String

by Dino Esposito, our WURFL Developer Evangelist for Microsoft Technologies and .NET Guru

When we designed the WURFL cloud API, we mostly thought of a web-based world. For this reason, the ASP.NET API requires an HttpContext object and uses it to understand just about  everything about the incoming request. To proceed from a solid frame of reference, let’s say that you start with code similar to this:

var config = new DefaultCloudClientConfig { ApiKey = "..." };
var manager = new CloudClientManager(config);

The manager object is the console that gives you access to the cloud-stored information about the device. On the cloud client manager object you usually call the following override of the GetDeviceInfo method:

var context = HttpContext.Current;
var info = manager.GetDeviceInfo(context, new[] { "is_wireless_device", "is_tablet" });

In general, you retrieve the HTTP context in other ways than showed here, but this doesn’t change the basic facts. For example, in ASP.NET Web Forms you can access the HTTP context from the Page object; in ASP.NET MVC instead you get the reference from the controller instance that is serving the request.

Internally, the cloud client manager uses the provided HTTP context to retrieve cookies and HTTP headers (including the user agent string). It consumes the information in order to serve the corresponding values for the specified WURFL capabilities.

So far so good.

Overriding the User Agent String (PREMIUM only)

When the HTTP context is used, as a developer you do not have direct control over the user agent string (UAS) being passed. The user agent is supplied directly from the HTTP request. Is there a way to work around this and force the WURFL cloud backend to process a “given” user agent string instead of the current HTTP request? You bet!

As you know, the WURFL cloud comes in several flavors—Basic, Standard, and Premium. We made this UAS override feature available only to our Premium users. Here’s how one would use it:

var manager = new CloudClientManager(config);
var ua = "...";
var wurflRequest = new WurflCloudRequest(context) { UserAgent = ua };
var info = manager.GetDeviceInfo(wurflRequest, new[] {
               "is_wireless_device", "is_smartphone", "physical_screen_width" });

In this way, any user agent HTTP header that may be carried with the request is ignored. The user agent string processed to match a WURFL device is the one you provide. At the same time, other headers and cookies coming with the request are processed as usual.

Mocking HttpContextBase Maaaybe?

The ASP.NET cloud API is available for the .NET Framework 2.0 and .NET Framework 4.0 and newer versions. In the version compiled against the .NET Framework 4.0 the method GetDeviceInfo on the cloud client manager has the following signature:

public DeviceInfo GetDeviceInfo(HttpContextBase context, String[] capabilities)

The API for the .NET Framework 2.0, instead, uses HttpContext instead of HttpContextBase. Can you recall the difference between HttpContext and HttpContextBase?

HttpContext is the old-fashioned class representing the HTTP context of an ASP.NET request. HttpContext has no base class and no virtual methods. It’s a monolith and gives a great contribution to making ASP.NET a hard-to-test framework. On the other hand, HttpContextBase is an abstract class serving as a testable replacement for HttpContext. First introduced in ASP.NET MVC, it was the ported back to the whole ASP.NET platform with the release of ASP.NET 4.0.

What’s the point? You can create your own class derived from HttpContextBase and pass it to GetDeviceInfo to bypass the issue of overriding the user agent string in a Base WURFL cloud library. If you can do that, it should work. However, we want to call your attention on a key fact: HttpContextBase is a delicate class. It is relatively easy to mock with the help of an ad hoc mocking framework, but it is hard to clone programmatically. Moreover, it may require a lot of code on your own.

Definitive Solution Coming Up

So you provided feedback and we got the message. With the WURFL Cloud API 1.1 for ASP.NET, both Base and Premium users will be able to make a request to the cloud passing in the sole user agent string.  How to do it? It couldn’t be easier; we just added a new override for the GetDeviceInfo method on the clould client manager class:

public DeviceInfo GetDeviceInfo(String userAgent, String[] capabilities)

The code shown above therefore changes as below:

var ua = "...";
var info = manager.GetDeviceInfo(ua, new[] { "is_wireless_device", "is_tablet" });

Note, however, that only Premium users will be able to pass the sole user agent string as well as a custom user agent string and the HTTP context. Base users can specify either the HTTP context or the sole user agent string, but not the two things together.

From the WURFL cloud with love and development passion!