Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » General » Downloads
 
Add your own
alternative version

Browser Detection using ASP.NET

, 6 May 2009
Using and updating your machine.config file to better detect browser type in ASP.NET
/*
Used to determine Browser Capabilities by the Browsers UserAgent string.
Copyright (C) 2002-Present  Owen Brady (Ocean at xvision.com)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
using System;
namespace Ocean.Web.HttpCapabilities
{
	/// <summary>
	/// Summary description for HttpBrowserCapabilities.
	/// </summary>
	public class Settings
	{
		/// <summary>
		/// 
		/// </summary>
		private System.Collections.Specialized.StringDictionary UseVars;
		/// <summary>
		/// 
		/// </summary>
		private System.Collections.Specialized.StringDictionary Items;
		/// <summary>
		/// 
		/// </summary>
		private System.Collections.ArrayList Nodes;
		/// <summary>
		/// 
		/// </summary>
		private System.Web.HttpRequest Request;
		/// <summary>
		/// 
		/// </summary>
		private string UserAgent;
		/// <summary>
		/// 
		/// </summary>
		private string this [string key]
		{
			get 
			{ 
				if (key==null || key =="")
				{
					key ="%{HTTP_USER_AGENT}";
				}
				if (UseVars.ContainsKey(key.ToLower())==true)
				{
					return UseVars[key.ToLower()]; 
				}
				
				if (key[0]=='%' && key[1]=='{' && key[key.Length -1]=='}')
				{
					key = key.Substring(2);
					key = key.Substring(0,key.Length -1);
				}

				if (Items.ContainsKey(key.ToLower())==true)
				{
					return Items[key.ToLower()]; 
				}				

				return "";
			}
		}


		/// <summary>
		/// Get the current settings from the xml config file
		/// </summary>
		public static Settings GetSettings() 
		{
			Settings settings = (Settings)System.Configuration.ConfigurationSettings.GetConfig("Ocean.Web/BrowserCaps");
			if(settings == null)
			{
				return Settings.Default;
			}
			else
			{
				return settings;
			}
		}

		/// <summary>
		/// The default settings.  Deflate + normal.
		/// </summary>
		public static Settings Default 
		{
			get 
			{ 
				return new Settings(); 
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		public void AddSettings(System.Xml.XmlNode node)
		{
			Nodes.Add(node);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="File"></param>
		public void AddSettings(Ocean.Web.HttpCapabilities.EmbededFile File)
		{
			//------------------------------------------------------
			//
			//------------------------------------------------------
			System.Reflection.Assembly assem = this.GetType().Assembly;

			string Resources="Ocean.Web.HttpCapabilities.Resources.";
			switch (File)
			{
				case Ocean.Web.HttpCapabilities.EmbededFile.BrowserCap:
					Resources+="xml.BrowserCap";
					break;
				case Ocean.Web.HttpCapabilities.EmbededFile.MobileCap:
					Resources+="xml.Mobile";
					break;
				case Ocean.Web.HttpCapabilities.EmbededFile.SpidersBots:
					Resources+="xml.SpidersBots";
					break;
				case Ocean.Web.HttpCapabilities.EmbededFile.CodeProject:
					Resources+="xml.CodeProject";
					break;
			}

			foreach( string resourceName in assem.GetManifestResourceNames()) 
			{
				if (resourceName==Resources)
				{
					//---------------------------------------------------------------------
					//The javascript code which we need has been embeded as a resource in this
					//dot.net libary dll. So all we have to do is use the stream method to get
					//the raw stream from the dll, so that we can work with it.
					//---------------------------------------------------------------------
					System.Xml.XmlDocument Doc = new System.Xml.XmlDocument();
					Doc.Load(assem.GetManifestResourceStream(resourceName));
					this.AddSettings(Doc.DocumentElement);
				}
			}
		}
		/// <summary>
		/// 
		/// </summary>
		private void Reset()
		{
			UseVars= new System.Collections.Specialized.StringDictionary();
			Items = new System.Collections.Specialized.StringDictionary();
		}
		/// <summary>
		/// 
		/// </summary>
		public Settings()
		{
			Reset();
			Nodes = new System.Collections.ArrayList();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="File"></param>
		public Settings(Ocean.Web.HttpCapabilities.EmbededFile File):this()
		{
			this.AddSettings(File);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		public Settings(System.Xml.XmlNode node):this()
		{
			this.AddSettings(node);
		}	
		/// <summary>
		/// 
		/// </summary>
		/// <param name="useragent"></param>
		/// <returns></returns>
		public Result Process(string useragent)
		{
			System.Diagnostics.Trace.WriteLine("Process");
			Reset();
			UserAgent = useragent;
			ProcessBase();
			return new Ocean.Web.HttpCapabilities.Result(Items);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public Result Process(System.Web.HttpRequest request)
		{
			Reset();
			Request =request;
			UserAgent =request["HTTP_USER_AGENT"];
			ProcessBase();
			return new Ocean.Web.HttpCapabilities.Result(Items);
		}
		/// <summary>
		/// 
		/// </summary>
		internal void ProcessBase()
		{
			System.Diagnostics.Trace.WriteLine("ProcessBase");
			foreach (System.Xml.XmlNode node in Nodes)
			{
				ProcessNode(node);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		internal void ProcessNode(System.Xml.XmlNode node)
		{
			System.Diagnostics.Trace.WriteLine("ProcessNode");
			if (node==null || node.ChildNodes ==null)
			{
				return;
			}
			foreach (System.Xml.XmlNode E in node.ChildNodes)
			{
				switch (E.Name.ToLower())
				{
					case "result":
						//do nothing with this currently
						break;
					case "use":
						ProcessUse(E);
						break;
					case "#text":
						ProcessItems(E);
						break;
					case "filter":

						if( E.HasChildNodes ==true)
						{
							Processfilter(E);
						}
						break;
				}
			}
		
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		/// <returns></returns>
		internal bool ProcessCase(System.Xml.XmlNode node)
		{
			return ProcessCase(node,null);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		/// <param name="RegMatch"></param>
		/// <returns></returns>
		internal bool ProcessCase(System.Xml.XmlNode node,Ocean.Web.HttpCapabilities.CaseFilter RegMatch)
		{
			System.Diagnostics.Trace.WriteLine("ProcessCase");
			string matchvalue ="";
			string matchwith ="";
			if (node.Attributes["match"]!=null)
			{
				matchvalue = node.Attributes["match"].Value;
			}
			if (node.Attributes["with"]!=null)
			{
				matchwith = node.Attributes["with"].Value;

				if (matchwith.Length >0 && matchwith[0]=='$' && RegMatch.CountGroups >0)
				{
					matchwith =RegMatch.Result(matchwith);
				}
				else if (matchwith.Length >0 && matchwith[0]=='%')
				{
					matchwith = this[matchwith];
				}
			}
			else
			{
				matchwith = this[matchwith];
			}
			
			Ocean.Web.HttpCapabilities.CaseFilter LocalMatch = new Ocean.Web.HttpCapabilities.CaseFilter(matchvalue,matchwith);
			if (LocalMatch.Success ==false)
			{
				return false;
			}
			else
			{
				System.Diagnostics.Trace.WriteLine(string.Format("value:{0}\twith:{1}",matchvalue,matchwith));
			}
			foreach (System.Xml.XmlNode E in node.ChildNodes)
			{
				switch (E.Name.ToLower())
				{
					case "#text":
						string raw = E.Value;
						if (LocalMatch.CountGroups >0)
						{
							raw = LocalMatch.Result(raw);
						}
						if (RegMatch!=null && RegMatch.CountGroups >0)
						{
							raw = RegMatch.Result(raw);
						}
						ProcessItems(raw);
						break;
					case "case":
						if( E.HasChildNodes ==true)
						{
							bool CaseValue=false;
							if (LocalMatch.CountGroups >1)
							{
								CaseValue = ProcessCase(E,LocalMatch);
							}
							else
							{
								CaseValue = ProcessCase(E,RegMatch);
							}
							if (CaseValue==true)
							{
								return true;
							}
						}
						break;
					case "filter":
						if( E.HasChildNodes ==true)
						{
							if (LocalMatch.CountGroups >1)
							{
								Processfilter(E,LocalMatch);
							}
							else
							{
								Processfilter(E,RegMatch);
							}
						}
						break;
				}
			}

			return true;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		internal void Processfilter(System.Xml.XmlNode node)
		{
			Processfilter(node,null);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		/// <param name="RegMatch"></param>
		internal void Processfilter(System.Xml.XmlNode node,Ocean.Web.HttpCapabilities.CaseFilter RegMatch)
		{
			System.Diagnostics.Trace.WriteLine("Processfilter");
			string matchvalue ="";
			string matchwith ="";
			if (node.Attributes["match"]!=null)
			{
				matchvalue = node.Attributes["match"].Value;
			}
			if (node.Attributes["with"]!=null)
			{
				matchwith = node.Attributes["with"].Value;

				if (matchwith.Length >0 && matchwith[0]=='$' && RegMatch.CountGroups >0)
				{
					matchwith =RegMatch.Result(matchwith);
				}
				else if (matchwith.Length >0 && matchwith[0]=='%')
				{
					matchwith = this[matchwith];
				}
			}
			else
			{
				matchwith = this[matchwith];
			}
			if (matchwith==null)
			{
				matchwith =string.Empty;
			}
			
			Ocean.Web.HttpCapabilities.CaseFilter LocalMatch = new Ocean.Web.HttpCapabilities.CaseFilter(matchvalue,matchwith);
			if (LocalMatch.Success ==false)
			{
				return ;
			}
			foreach (System.Xml.XmlNode E in node.ChildNodes)
			{
				switch (E.Name.ToLower())
				{
					case "#text":
						string raw = E.Value;
						if (LocalMatch.CountGroups >0)
						{
							raw = LocalMatch.Result(raw);
						}
						if (RegMatch!=null && RegMatch.CountGroups >0)
						{
							raw = RegMatch.Result(raw);
						}
						ProcessItems(raw);
						break;
					case "case":
						if( E.HasChildNodes ==true)
						{
							bool CaseValue=false;
							if (LocalMatch.CountGroups >1)
							{
								CaseValue = ProcessCase(E,LocalMatch);
							}
							else
							{
								CaseValue = ProcessCase(E,RegMatch);
							}
							if (CaseValue==true)
							{
								return;
							}
						}
						break;
					case "filter":
						if( E.HasChildNodes ==true)
						{
							if (LocalMatch.CountGroups >1)
							{
								Processfilter(E,LocalMatch);
							}
							else
							{
								Processfilter(E,RegMatch);
							}
						}
						break;
				}
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		internal void ProcessUse(System.Xml.XmlNode node)
		{
			System.Diagnostics.Trace.WriteLine("ProcessUse");
			string matchvar = node.Attributes["var"].Value;
			string matchas  = null;
			string HeaderResult ="";
			if (node.Attributes["as"]!=null)
			{
				if (node.Attributes["as"].Value!=null)
				{
					matchas  = node.Attributes["as"].Value.Trim();
				}
				else
				{
					matchas =string.Empty;
				}
			}
			else
			{
				matchas="HTTP_USER_AGENT";
			}
			System.Diagnostics.Trace.WriteLine("matchas:{0}",matchas);

			if (matchvar!=null)
			{
				if (matchas!=string.Empty)
				{
					matchas ="%{" + matchas.Trim() +"}";
					if (matchas=="%{HTTP_USER_AGENT}")
					{
						HeaderResult = UserAgent;
					}
					else if (Request!=null && Request[matchvar]!=null && Request[matchvar]!=string.Empty)
					{
						HeaderResult = Request[matchvar];
					}
					else
					{
						//no header that matches it so we have to put something there
						//so I put in an empty string.
						HeaderResult =string.Empty;
					}
					if (UseVars.ContainsKey(matchas)==false)
					{
						UseVars.Add(matchas,HeaderResult);
					}
					else
					{
						UseVars[matchas] = HeaderResult;
					}
				}
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="node"></param>
		internal void ProcessItems(System.Xml.XmlNode node)
		{
			ProcessItems(node.Value);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="raw"></param>
		internal void ProcessItems(string raw)
		{
			System.Diagnostics.Trace.WriteLine("ProcessItems");
			//--------------------------------------------------
			//removing all the tabs out of the raw string
			//--------------------------------------------------
			while (raw.IndexOf("\t")>-1)
			{
				raw = raw.Replace("\t","");
			}
				
			//--------------------------------------------------
			//removing all the line feeds out of the raw string
			//--------------------------------------------------
			while (raw.IndexOf("\n")>-1)
			{
				raw = raw.Replace("\n","");
			}
			//--------------------------------------------------
			//removing all the double control breaks out of the 
			//raw string
			//--------------------------------------------------
			while (raw.IndexOf("\r\r")>-1)
			{
				raw = raw.Replace("\r\r","\r");
			}
				
			//--------------------------------------------------
			//removing all double blank spaces from the raw string
			//--------------------------------------------------
			while (raw.IndexOf("  ")>-1)
			{
				raw = raw.Replace("  "," ");
			}
			System.Text.RegularExpressions.Match M;
			M = System.Text.RegularExpressions.Regex.Match(raw,@"%{\w*}");
			while (M.Success==true)
			{
				for (int a=0;a<=M.Captures.Count -1;a++)
				{
					string s= M.Captures[a].Value;
					raw =raw.Replace(s,this[s]);
				}
				M = System.Text.RegularExpressions.Regex.Match(raw,@"%{\w*}");					
			}
			
			//--------------------------------------------------
			//Split the Array
			//--------------------------------------------------
			string[] itemsArray = System.Text.RegularExpressions.Regex.Split(raw,"\r");
			for (int i=0; i<= itemsArray.Length -1;i++)
			{
				itemsArray[i] = itemsArray[i].Trim();
				if(itemsArray[i]!="")
				{
					//--------------------------------------------------
					//only have to act if there is equal sign in the string
					//--------------------------------------------------
					if ( itemsArray[i].IndexOf("=")>-1)
					{
						string[] a = itemsArray[i].Split('=');
						a[1] = a[1].Trim();

						//--------------------------------------------------
						//always use lower case keys
						//--------------------------------------------------
						a[0] = a[0].Trim().ToLower();

						//--------------------------------------------------
						//just remove the quotes and move on
						//--------------------------------------------------
						while (a[1].IndexOf("\"")>-1)
						{
							a[1] = a[1].Replace("\"","");
						}

						//--------------------------------------------------
						//just making sure the varables are cleared out if they 
						//didn't take
						//--------------------------------------------------
						if (a[1].Length >2)
						{
							if (a[1].Substring(0,2) =="${")
							{
								a[1]=string.Empty;
							}
						}
						
						//--------------------------------------------------
						//this assigns the key/value pair to the string dictionary
						//--------------------------------------------------
						if (a[1]!=string.Empty)
						{
							if (Items.ContainsKey(a[0])==true)
							{
								Items[a[0]] = a[1];
							}
							else
							{
								Items.Add(a[0],a[1]);
							}
						}
					}					
				}
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Chris Maunder
Founder CodeProject
Canada Canada
Chris is the Co-founder, Administrator, Architect, Chief Editor and Shameless Hack who wrote and runs The Code Project. He's been programming since 1988 while pretending to be, in various guises, an astrophysicist, mathematician, physicist, hydrologist, geomorphologist, defence intelligence researcher and then, when all that got a bit rough on the nerves, a web developer. He is a Microsoft Visual C++ MVP both globally and for Canada locally.
 
His programming experience includes C/C++, C#, SQL, MFC, ASP, ASP.NET, and far, far too much FORTRAN. He has worked on PocketPCs, AIX mainframes, Sun workstations, and a CRAY YMP C90 behemoth but finds notebooks take up less desk space.
 
He dodges, he weaves, and he never gets enough sleep. He is kind to small animals.
 
Chris was born and bred in Australia but splits his time between Toronto and Melbourne, depending on the weather. For relaxation he is into road cycling, snowboarding, rock climbing, and storm chasing.
Follow on   Twitter   Google+   LinkedIn

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 6 May 2009
Article Copyright 2004 by Chris Maunder
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid