mostlylucid

STATIC ARCHIVE of mostlylucid.co.uk of old
posts - 916, comments - 758, trackbacks - 11

My Links

News

Archives

Post Categories

Misc. Coding

ASP.NET 4.0: Browser Capabilities Providers (esoterica warning!)

ASP.NET determines the capabilities of the browser with which a user is browsing your site using a feature called 'browser capabilities'. In ASP.NET 3.5 SP1 there are two main ways in which you can define the capabilities which a browser has:

1. To make the change for your entire machine. Go into C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers, find the browser you want to alter, find the specific capability you want to alter in the XML, change it then run aspnet_regbrowsers.exe -I from the VS Tools command line to rebuild the Browser Capabilities assembly and add it to the GAC...

2. To make a change for just a specific application. Add a *.browser file into a folder called app_browsers within your application which specifies the browser (or default) to which you want to apply these capabilities.

As so can see, both of these approaches are pretty limited, in that you really have to change XML files ; and in the first case, you have to restart your app as part of the aspnet_regbrowsers.exe process. In ASP.NET 4.0 we have added a feature called BrowserCapabilities Providers which, as the name suggests, allows you to build a provider allowing you to use your own code to determine Browser Capabilities from your own data store.

Why would you want to do this, well, browser files are notoriously hard to update (the ASP.NET team really hasn't touched them since ASP.NET 2.0), they're pretty complicated to work with and well...they're a strange XML syntax. Wouldn't it be cool if there was a common Browser Definition syntax, or a database containing a huge number of new browser definitions...or even a web service. Before you really couldn't use any of this with ASP.NET...now you can :-)

So, how do you use the new ASP.NET 4.0 Browser Capabilities Provider feature?

There are two main possibilities here, extend the ASP.NET Browser Capabilities definition functionality or totally replace it.

To replace the ASP.NET Browser Capabilities definition functionality:

1. Create a provider by sub-classing the HttpCapabilitiesProvider:

public class CustomProvider : HttpCapabilitiesProvider

{

public override HttpBrowserCapabilities

GetBrowserCapabilities(HttpRequest request)

{

HttpBrowserCapabilities browserCaps = new

HttpBrowserCapabilities();

Hashtable values = new Hashtable(180,

StringComparer.OrdinalIgnoreCase);

values[String.Empty] = request.UserAgent;

values["browser"] = "MyCustomBrowser";

browserCaps.Capabilities = values;

return browserCaps;

}

}

In this example we create a new HttpBrowserCapabilities object, specifying only the capability 'browser' to value 'MyCustomBrowser'.

2. Register the provider with the application.

In order to use a provider within an application, you need to add the provider attribute to the browserCaps section in Web.config or Machine.config,
note: it is also possible to define this within a <location> tag for specific directories within the app; e.g., a specific mobile directory.

<system.web>

<browserCaps provider="ClassLibrary2.CustomProvider, ClassLibrary2,

Version=1.0.0.0, Culture=neutral" />

</system.web>

Another way to 'plug in' the new BrowserCapabilities is to use code:

void Application_Start(object sender, EventArgs e)
{
HttpCapabilitiesBase.BrowserCapabilitiesProvider =
new ClassLibrary2.CustomProvider();
..
}

Note: This must be run in the Application_Start event as changing the BrowserProvider must happen before the first executes to ensure the cache remains in a valid state for the resolved HttpCapabilitiesBase object.

Adding Caching

The previous example has one major problem; this code would run on each call to get the HttpBrowserCapabilities which can happen multiple times in each request. For the example above it's not really a big deal as we don't really do much, but you can imagine that if your code does some significant work then this can be a huge overhead. So, how would you prevent this happening? Cache the HttpBrowserCapabilities object!

1. Again, create a provider by sub-classing the HttpCapabilitiesProvider:

public class CustomProvider : HttpCapabilitiesProvider

{

public override HttpBrowserCapabilities

GetBrowserCapabilities(HttpRequest request)

{

string cacheKey = BuildCacheKey();

int cacheTime = GetCacheTime();

HttpBrowserCapabilities browserCaps =

HttpContext.Current.Cache[cacheKey] as

HttpBrowserCapabilities;

If (browserCaps == null)

{

HttpBrowserCapabilities browserCaps = new

HttpBrowserCapabilities();

Hashtable values = new Hashtable(180,

StringComparer.OrdinalIgnoreCase);

values[String.Empty] = request.UserAgent;

values["browser"] = "MyCustomBrowser";

browserCaps.Capabilities = values;

HttpContext.Current.Cache.Insert(cacheKey,

browserCaps, null, DateTime.MaxValue,

TimeSpan.FromSeconds(cacheTime));

}

return browserCaps;

}

}

In the code above, in order to improve performance for each subsequent request we generate a cache key using their own BuildCacheKey() as well as the length of time to cache returned from their own GetCacheTime() method to enter the resolved HttpBrowserCapabilities object into cache and can then reuse this object on subsequent requests with matching User Agent string.

2. Register the provider with the application. See previous example.

Extending ASP.NET's Browser Capabilities' functionality

Great, so now we know how to create a new HttpBrowserCapabilities object which ASP.NET 4.0 uses. What about extending ASP.NET's Browser Capabilities functionality by adding new Browser Capabilities definitions to those ASP.NET currently ships with...WITHOUT using the XML definitions we mentioned previously?

1. To generate a Browser Capabilities Provider we create a class inheriting from the HttpCapabilitiesDefaultProvider as follows:

public class CustomProvider : HttpCapabilitiesDefaultProvider

{

public override HttpBrowserCapabilities

GetBrowserCapabilities(HttpRequest request)

{

HttpBrowserCapabilities browserCaps =

base.GetHttpBrowserCapabilities(request);

if (browserCaps.Browser == "Unknown")

{

browserCaps = MyBrowserCapabilitiesEvaulator(request);

}

return browserCaps;

}

}

Here we first use ASP.NET's Browser Capabilities functionality to try and identify the browser, however if no browser was identified based on the information defined in the request. In this code, we check for the browser being unidentified by checking for the string "Unknown' in the HttpBrowserCapabilities.Browser property and then we call into our own code (MyBrowserCapabilitiesEvaluator) to identify the correct browser using the information contained in the request.

3. Register the provider with the application. See the first example.

Adding new Capabilities to Existing Browser Capabilities Definitions

1. To generate a Browser Capabilities Provider the developer would create a class inheriting from the HttpCapabilitiesEvaluator as follows:

public class CustomProvider : HttpCapabilitiesDefaultProvider

{

public override HttpBrowserCapabilities

GetBrowserCapabilities(HttpRequest request)

{

HttpBrowserCapabilities browserCaps =

base.GetHttpBrowserCapabilities(request);

browserCaps.Frames = true;

browserCaps.Capabilities["MyCapability"] = "Bob";

return browserCaps;

}

}

In this case we have extended the shipped HttpCapabilitiesDefaultProvider class and obtained the HttpBrowserCapabilities object which the base method returns:

HttpBrowserCapabilities browserCaps =

base.GetHttpBrowserCapabilities(request);

By accessing the base method we are able to access the existing HttpBrowserCapabilities definition and add / modify a capability for this browser in their own code.

Note: There are two ways of specifying a browser capability:

1. The HttpCapabilitiesBase object contains an IDictionary names 'Capabilities', the developer can add any value to this discionary e.g, in this case adding a capability called 'MyCapability' with the value 'Bob'.

2. The second is through the use of properties on the HttpCapabilitiesBase object, in the case above the developer sets the value of 'Frames' to 'true'; in reality this is in fact an accessor for the Capabilities IDictionary and adds / retrieves this property from that IDictionary.

Note: This model applies to any property of HttpBrowserCapabilities, including Control Adapters.

2. Register the provider with the application. See the first example...

Print | posted on Monday, January 26, 2009 9:47 AM | Filed Under [ ASP.NET 4.0 ]

Feedback

# re: ASP.NET 4.0: Browser Capabilities Providers (esoterica warning!)

Its always good to learn tips like you share for blog posting. As I just started posting comments for blog and facing problem of lots of rejections. I think your suggestion would be helpful for me. I will let you know if its work for me too.

Thanks and keep post such a informative blogs.

6/26/2009 11:48 PM | tricks with poker chips

Comments have been closed on this topic.

Powered by: