ASP.Net HttpModule to detect and redirect mobile devices version 2.0

comments

Last year I wrote a post on how to setup an ASP.Net HttpModule that detects and redirects mobile devices so that you can show a different version of your site to users browsing your site using whatever hot new mobile device is going around. Since then the lay of the land has changed a bit, so i thought it was time to reassess the solution i recommended and offer you a new updated one for 2011. The great thing about this solution is it’s a lot more future proof, so hopefully i won’t have to write another blog post next year.

Due to the organizational restructuring of the team that developed and supported the Mobile Device Browser file, we will no longer have the resources to support and update this CodePlex project. The team will be providing two more releases – one on the 27th July 2010 and the final release on the 24th August 2010.

imageWhat does this mean? This means that when i recommended the Mobile Device Browser File project from Microsoft, i did so without knowing that the project was about to be canned. With this knowledge in hand, i wouldn’t have recommended this solution. Instead i would have pointed you to the 51 degrees’ Mobile Device Detection project.

51 Degrees

The project was originally created by a mobile device web development company called 51 Degrees that has released to the public their ASP.Net mobile device module. This project bases its data on the WURFL project over on SourceForge which has grown from a small error prone option to become known as the most complete device compatibility collection available.

This is great, as it means that, unlike the Mobile Device Browser File project, if the 51 degrees project was to stop tomorrow, you’d be able to get updated device lists to use with the code your wrote simply by updating your WURFL data file – so hopefully next year i won’t have to write another post.

“A Little Less Conversation…”

Go to the 51 Degrees Mobile Device Detection project site and download the latest “Enhance Package” – this package allows you to get setup in minutes.

image

Open the folder of your ASP.Net website, and then copy all the contents of the zip download except for the file README.rtf into your website root. This copies a new library into your Bin directory, and some WURFL device files into your App_Data directory.

Now Open the README.rtf to get the config sections that you’re going to copy into your website’s web.config file.

Inside this word document, first you’ll find the config definition sections that need to be added to the top of your webconfig.

My example web.config before pasting in the sections:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                    <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
                    <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                </sectionGroup>
            </sectionGroup>
        </sectionGroup>
    </configSections>
……

My example web.config header after copying in the sections for our mobile module (new section in bold):

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                    <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
                    <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                </sectionGroup>
            </sectionGroup>
        </sectionGroup>
        <sectionGroup name="fiftyOne">
            <section name="log" type="FiftyOne.Foundation.Mobile.Configuration.LogSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
            <section name="redirect" type="FiftyOne.Foundation.Mobile.Configuration.RedirectSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
            <section name="wurfl" type="FiftyOne.Foundation.Mobile.Detection.Wurfl.Configuration.WurflSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
        </sectionGroup>
    </configSections>

Now we need to add the actual configuration section that stores configuration that lets out HttpModule know how to behave. You can paste this just below the above configSections part of your web.config.

What this configuration will give us out of the box:

  • All mobile devices on their first request will be sent to the folder /mobile/
  • Only the first request from a mobile device will be redirected, allowing you to them link back to any page that was requested originally – this enables users that were emailed a link by a friend still be able to view the non mobile version if you place a link to the querystring key “originalUrlAsQueryString” – this will be added to the request of the mobile page redirected to when the user visits for the first time.
  • Any request made to the folder /mobile/ will be ignored by the mobile detection module
  • A 20 minute timeout on the users visit before they are considered new again if they visit from a mobile device again.
  • A log file of requests will be written to the file ~/App_Data/Log.txt
<fiftyOne>
<redirect
firstRequestOnly="true" mobileHomePageUrl="~/mobile/" originalUrlAsQueryString ="true" timeout="20" devicesFile="~/App_Data/Devices.dat" mobilePagesRegex="~/mobile/"> </redirect>


<
log logFile="~/App_Data/Log.txt" logLevel="Info"/>
<wurfl wurflFilePath="~/App_Data/wurfl.xml.gz" newDevicesURL="http://devices.51degrees.mobi/New.ashx" newDeviceDetail="maximum"> <wurflPatches> <add name="browser_definitions" filePath="~/App_Data/web_browsers_patch.xml" enabled="true"/> </wurflPatches> </wurfl>
</
fiftyOne>

Now you need to add the HttpModule Sections of your web.config

For IIS 6:

<httpModules>
    <add name="Detector" type="FiftyOne.Foundation.Mobile.Detection.DetectorModule, FiftyOne.Foundation"/>
</httpModules>

For IIS 7/7.5:

<system.webServer>
    <modules>
        <remove name="Detector"/>
        <add name="Detector"  type="FiftyOne.Foundation.Mobile.Detection.DetectorModule, FiftyOne.Foundation"/>
    </modules>
</system.webServer>

This leaves you with an ASP.Net HttpModule that redirects all mobile device requests coming to your site to the path /mobile/ allowing you to place your entire mobile site inside a subfolder (this can be a subdomain or something similar if you don’t want it to be the same site). This can be anything you want depending on what you set the above fiftyOne web.config sections to, but for the purposes of this demo simply place your own default.htm/default.aspx inside this folder.

Time to test

So the next question is, apart from using a smart phone to test this what do you do? Install FireFox, and then head over to https://addons.mozilla.org/en-US/firefox/addon/user-agent-switcher/ to install the User Agent Switcher. This cool little add-on allows you to test sites by cloaking your user agent header string and sending something else. It comes installed with an default iPhone 3.0 config option.

Open Firefox after installing User Agent Switcher

Select Tools > Default User Agent > iPhone 3.0

image

Now enter the URL for your website. It should now redirect to your new mobile site! Have a bit of a play around with the settings and you’ll be cranking out mobile sites like no ones business. Too easy.