<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Stardeveloper</title>
<link>http://www.stardeveloper.com/</link>
<description>Learn web application development.</description>
<language>en-us</language>
<ttl>60</ttl>
<pubDate>Thu, 09 May 2013 02:58:29 GMT</pubDate><generator><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2008112101&amp;page=1]]></generator><copyright>Copyright 1999 - 2013 Stardeveloper.com, All Rights Reserved.</copyright>
<lastBuildDate>Sun, 12 Jun 2011 00:00:00 GMT</lastBuildDate>
<item>
<title>Developing your first JSP Application in Eclipse</title>
<link><![CDATA[http://www.stardeveloper.com/tutorial/developing-your-first-jsp-application-in-eclipse]]></link>
<description><![CDATA[<p><b>Eclipse</b> provides complete development environment for working with <b>JSP applications</b>. It simplifies the task of creating both dynamic (JSP pages, Servlets, JavaBeans and Java classes) and static content (CSS and JavaScript files). Built-in support for debugging, testing and deployment takes the productivity to an entirely new level.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse-development-environment.png" width="606" height="384" alt="Developing JSP applications in Eclipse" title="A JSP application running in Eclipse" />
	<div class="imagedesc">A JSP application running in Eclipse</div>
</div>

<p>In this tutorial, we will learn how to create a new project in Eclipse for developing a dynamic JSP web application. The web application for the purpose of simplicity at this time, will be a single page JSP application that will show current date and time on the server. The application will run on Apache Tomcat 7.0.</p>

<h2>Prerequisites</h2>

<p>This tutorial assumes that you have working installations of both <em>Apache Tomcat</em> and <em>Eclipse IDE for Java EE development</em> on your computer:</p>

<ol>
	<li><a href="http://www.stardeveloper.com/tutorial/installing-apache-tomcat-7.0" title="Learn how to install Apache Tomcat on Microsoft Windows">Installing Apache Tomcat 7.0</a></li>
	<li><a href="http://www.stardeveloper.com/tutorial/installing-eclipse-for-jsp-development" title="Learn how to install Eclipse edition for JSP development on Microsoft Windows">Installing Eclipse for JSP Development</a></li>
</ol>

<h2>Step 1: Start Eclipse</h2>

<p>Assuming that you installed Eclipse in <code>eclipse</code> folder in your <code>C:\</code>, go to the <code>C:\eclipse</code> folder and double-click <code>eclipse.exe</code> file, as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/running-eclipse.png" width="176" height="350" alt="Eclipse folder" title="Start Eclipse by double-clicking C:\eclipse\eclipse.exe file." />
	<div class="imagedesc">Eclipse folder</div>
</div>

<p>Eclipse boots up and shows the welcome screen:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse-ide.png" width="637" height="461" alt="Eclipse IDE" title="Main Eclipse Window" />
	<div class="imagedesc">Eclipse IDE</div>
</div>

<h2>Step 2: Create new project</h2>

<p>Now, in the Eclipse IDE, click <code>File -> New -> Dynamic Web Project</code>. New Dynamic Web Project window pops up as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/new-dynamic-web-project-window.png" width="603" height="713" alt="New Dynamic Web Project window" />
	<div class="imagedesc">New Dynamic Web Project window</div>
</div>

<p>Enter 'Project name' as &quot;First JSP Project&quot;. Leave rest of the settings as they are and click 'Next'.</p>

<p>Next window asks for adding paths to folders containing pre-existing Java source code files. Since this is a new project and we don't have any other source code folders, we'll just accept the default source code folder of <code>src</code>. Click 'Next' to proceed forward.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/source-code-folders-window.png" width="603" height="713" alt="Add source code folders" />
	<div class="imagedesc">Source code folders options</div>
</div>

<p>Next window asks for web module configuration settings. A <em>web module</em> is a small JSP application that can either be run as a stand-alone application or it can be a component of a much larger enterprise application. An <em>enterprise application</em> can contain one or web modules along with other modules.</p>

<p>We accept the default 'Context root' and 'Content directory' folder names and leave the 'Generate web.xml deployment descriptor' option unchecked. We click 'Finish' and let Eclipse create folders, files and structure for new JSP application.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/configure-web-module-settings-window.png" width="603" height="713" alt="Configure web module settings window" />
	<div class="imagedesc">Configure web module settings window</div>
</div>

<h2>Step 3: Examining the project</h2>

<p>Eclipse opens our 'First JSP Project' project in a new window.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/first-jsp-project-window.png" width="672" height="760" alt="First JSP Project window" />
	<div class="imagedesc">First JSP Project window</div>
</div>

<p>If we expand the 'First JSP Project' node in the 'Project Explorer' window, we can see the names and contents of the different folders that Eclipse has created for us:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse-project-explorer-window.png" width="296" height="309" alt="Project Explorer window" />
	<div class="imagedesc">Project Explorer window</div>
</div>

<p>Among all the folders that Eclipse has created for our project, the one important to us now is <code>WebContent</code> folder. It is this folder that should contain the web content like JSP pages, static HTML pages, CSS and JavaScript files, etc. It is this folder where we'll create our JSP file for this project.</p>

<h2>Step 4: Add new JSP page</h2>

<p>Now left-click the 'First JSP Project' node in the 'Project Explorer' window to select it. Then right-click to see the list of options. Select <code>New -> JSP File</code>. 'New JSP File' window pops up as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/new-jsp-file-window.png" width="525" height="604" alt="New JSP File window" />
	<div class="imagedesc">New JSP File window</div>
</div>

<p>Enter 'File name' as &quot;index.jsp&quot;, keep the 'WebContent' folder selected and click 'Next'. 'Select JSP Template' window appears as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/select-jsp-template-window.png" width="525" height="604" alt="Select JSP Template window" />
	<div class="imagedesc">Select JSP Template window</div>
</div>

<p>Select 'New JSP File (xhtml)' template from the template names in the left column and click 'Finish'.</p>

<p>Eclipse creates a new JSP file from the template we selected and puts in enough HTML code along with a JSP directive to give us a head-start for adding further code to this file.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/index-jsp-window.png" width="624" height="465" alt="Our index.jsp JSP file in its window" />
	<div class="imagedesc">JSP File window</div>
</div>

<p>Now replace code in the <code>index.jsp</code> file by the code given below:</p>

<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot; ?&gt;
&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=ISO-8859-1&quot;
    pageEncoding=&quot;ISO-8859-1&quot;%&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=ISO-8859-1&quot; /&gt;
&lt;title&gt;First JSP Page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;p&gt;Current date and time: &lt;%= new java.util.Date().toString() %&gt;&lt;/p&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>

<p>The code is pretty much the same as it was except that I set the title of the page to &quot;First JSP Page&quot; and added one line of HTML intermixed with JSP code to display the current date and time on the server.</p>

<h2>Step 5: Configuring Eclipse to use Apache Tomcat</h2>

<p>Now that we have a JSP page and a pretty basic JSP web application, we want to run this application on a Servlet container. We have already <a href="http://www.stardeveloper.com/tutorial/installing-apache-tomcat-7.0" title="Learn how to install Apache Tomcat 7.0">installed Apache Tomcat 7.0</a> on our computer. We will now configure Eclipse to use that server as the Servlet container for our JSP application.</p>

<p>Click <code>Run -> Run</code> in the Eclipse window. This should make Eclipse pop up a 'Run On Server' window as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/run-on-server-window.png" width="525" height="648" alt="Run On Server window" />
	<div class="imagedesc">Run On Server window</div>
</div>

<p>Now, click to expand 'Apache' node from the list of servers. Then select 'Tomcat v7.0 Server' from the list of options. Check the 'Always use this server when running this project' option and leave rest of the options untouched and proceed to click 'Next' as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/select-server-type-window.png" width="525" height="648" alt="Selecting Servlet container for our JSP application" title="Selecting Apache Tomcat v7.0 from list of servers to run with our JSP application" />
	<div class="imagedesc">Configuring Eclipse to use Apache Tomcat 7.0</div>
</div>

<p>'Tomcat Server' configuration window opens up and asks for the path to the installation folder of Apache Tomcat 7.0. Click 'Browse' to select the Tomcat installation folder on your computer and click 'Finish'.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/configuring-tomcat-server-installation-directory.png" width="525" height="648" alt="Selecting Tomcat installation directory" title="Selecting Apache Tomcat v7.0 from list of servers to run with our JSP application" />
	<div class="imagedesc">Selecting Tomcat installation directory</div>
</div>

<h2>Step 6: Running our JSP application</h2>

<p>Eclipse configures the JSP application to use the Apache Tomcat server 7.0. Next, it automatically starts the Tomcat server in the background and opens the <code>index.jsp</code> page in a new tab as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/running-index-jsp-page.png" width="434" height="121" alt="index.jsp running on the Tomcat server" />
	<div class="imagedesc">index.jsp running on the Tomcat server</div>
</div>

<div class="note">You have successfully configured your JSP application to use Apache Tomcat 7.0 to run your application. From next time onwards, you can run your JSP application with a click of a button. You will not have to go through the configuration steps again.</div>

<p>Congratulations! You just finished creating a new JSP project in Eclipse, configured Eclipse to use Apache Tomcat 7.0 with your JSP project, and then finished running your JSP application successfully for the first time.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/tutorial/developing-your-first-jsp-application-in-eclipse]]></guid>
<author>Faisal Khan</author>
<pubDate>Sun, 12 Jun 2011 00:00:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>Installing Eclipse for JSP Development</title>
<link><![CDATA[http://www.stardeveloper.com/tutorial/installing-eclipse-for-jsp-development]]></link>
<description><![CDATA[<p><b>Eclipse</b> is a free and open source IDE (Integrated Development Environment) for developing a variety of applications from console and GUI applications on the client-side to web applications on the server. It has specific editions for different programming languages. In case of JSP, it offers <em>Eclipse IDE for Java EE Developers</em> for developing JSP based web applications.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse.png" width="455" height="295" alt="Eclipse" title="Eclipse" />
	<div class="imagedesc">Eclipse</div>
</div>

<p>The purpose of an IDE is to make the task of developing applications much easier. In the context of JSP web applications, Eclipse supports syntax coloring and highlighting, intellisense and code completion. It supports TDD (Test Driven Deployment). It has built-in support for debugging and allows one-click compilation and deployment of JSP applications.</p>

<p>In this tutorial, we will download and install 'Eclipse IDE for Java EE Developers' that will allow us to develop, test and run JSP web applications with <a href="http://www.stardeveloper.com/tutorial/installing-apache-tomcat-7.0" title="Tutorial: Installing Apache Tomcat on Microsoft Windows">Apache Tomcat 7.0</a> as the Servlet container.</p>

<h2>Step 1: Download Eclipse</h2>

<p>Open your browser and visit <a href="http://www.eclipse.org/downloads/">Eclipse Downloads</a> page. As shown in the figure below, click the download link for 'Eclipse IDE for Java EE Developers' and choose 32 or 64 bit version depending on the Operating System on your computer:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/downloading-eclipse.png" width="720" height="280" alt="Downloading Eclipse IDE for Java EE developers" title="Downloading Eclipse..." />
	<div class="imagedesc">Downloading Eclipse IDE for JSP development</div>
</div>

<h2>Step 2: Unzip Eclipse</h2>

<p>The file that you just finished downloading will have a name of something like <code>eclipse-jee-helios-SR2-win32-x86_64.zip</code>. Now, unzip this zip file into a new folder on your <code>C:\</code> drive. You can choose any drive but I chose <code>C:\</code> for the purpose of simplicity.</p>

<p>Next, create a new folder with the name of 'eclipse' in that drive and then unzip <code>eclipse-jee-helios-SR2-win32-x86_64.zip</code> in that folder.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/unzipping-eclipse-ide-jee-zip-file.png" width="580" height="350" alt="Unzipping Eclipse zip file" title="Unzipping Eclipse..." />
	<div class="imagedesc">Unzipping Eclipse zip file</div>
</div>

<p>After the unpacking is complete, this is what your <code>C:\</code> should look like:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse-folder.png" width="185" height="347" alt="Eclipse folder" title="Eclipse folder" />
	<div class="imagedesc">Eclipse folder</div>
</div>

<h2>Step 3: Running Eclipse</h2>

<p>Now go to the <code>C:\eclipse</code> folder and double-click <code>eclipse.exe</code> file as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/running-eclipse.png" width="176" height="350" alt="Running Eclipse" title="Start Eclipse by double-clicking the 'Eclipse.exe' file" />
	<div class="imagedesc">Running Eclipse</div>
</div>

<p>Eclipse starts up! First it will ask you for the location of default workspace. When you select a location and proceed next, Eclipse's default welcome screen shows up as shown in the image below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/eclipse-ide.png" width="637" height="461" alt="Eclipse IDE" title="Main Eclipse Window" />
	<div class="imagedesc">Eclipse IDE</div>
</div>

<p>Congratulations! You have successfully downloaded and installed Eclipse IDE for JSP development on your computer. You are now ready to start developing JSP web applications.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/tutorial/installing-eclipse-for-jsp-development]]></guid>
<author>Faisal Khan</author>
<pubDate>Thu, 09 Jun 2011 00:00:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>Installing Apache Tomcat 7.0</title>
<link><![CDATA[http://www.stardeveloper.com/tutorial/installing-apache-tomcat-7.0]]></link>
<description><![CDATA[<p><em>Apache Tomcat</em> is a free and open source Servlet container for JavaServer Pages. With version 7.0, it supports Java Servlet spec 3.0 and JSP spec 2.2.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/apache-tomcat-versions.png" width="565" height="72" alt="Apache Tomcat versions" title="Apache Tomcat versions as corresponding to Servlet/JSP specs" />
	<div class="imagedesc">Apache Tomcat versions</div>
</div>

<p>It is very easy to install on your computer. You can use it to develop and run web applications. A web application in the context of JavaServer Pages means developing an application that makes use of JSP pages, Servlets, Filters, JDBC, JSP custom tags and other Java based server-side technologies.</p>

<p>In the rest of this tutorial, I will walk you through installing Apache Tomcat 7.0 server on your Windows Operating System.</p>

<h2>Step 1: Download and install JDK 6.0</h2>

<p>If you already don't have JDK (Java Development Kit) 6.0 installed on your system then you should visit <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Java SE Downloads</a> page and download latest JDK 6.0 release build along with all the documentation on your computer.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/downloading-jdk-6.0.png" width="552" height="478" alt="Downloading JDK 6.0" title="Downloading latest JDK 6.0 release build along with all the documentation." />
	<div class="imagedesc">Downloading JDK 6.0</div>
</div>

<p>As shown in the image above, a JDK includes both the JRE (Java Runtime Environment) to run Java based applications (like Apache Tomcat server) and applets, and Java compiler and debugger to assist you in developing Java applications.</p>

<h3>How to know which version of Java you have on your computer?</h3>

<p>If you are unsure which version of Java is installed on your computer then open Command Prompt, enter the following command and press the Enter button:</p>

<pre>java -version</pre>

<p>If Java is installed on your system and the full path to <code>Java.exe</code> is included in the <code>PATH</code> environment variable on your computer then Java version information should appear on your screen as shown below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/java-version-information.png" width="677" height="266" alt="Java version information" title="Java -version command displays Java version installed on your computer." />
	<div class="imagedesc">Java version information</div>
</div>

<p>Now that you have a working copy of latest release build of JDK 6.0 on your computer, you should proceed to download Apache Tomcat server.</p>

<h2>Step 2: Download Apache Tomcat</h2>

<p>Go to the download page for <a href="http://tomcat.apache.org/download-70.cgi">Apache Tomcat 7.0</a>. Scroll down the page a little until you get to <i>Binary Distributions</i>.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/downloading-apache-tomcat-7.0.png" width="440" height="186" alt="Downloading Apache Tomcat 7.0" title="Downloading latest binary build of Apache Tomcat 7.0" />
	<div class="imagedesc">Downloading Apache Tomcat 7.0</div>
</div>

<p>Click on the appropriate link for your Operating System to download the file on your computer. In my case, I chose &quot;64-bit Windows zip&quot; as I was running Windows 7 on a 64-bit processor.</p>

<p>Now that you have the latest binary build of Apache Tomcat 7.0 on your computer, proceed to the unpack the zip file.</p>

<h2>Step 3: Unzip Apache Tomcat</h2>

<p>Now unzip the downloaded zip file into a convenient location on your hard drive. In my case, I unzipped it into &quot;C:\apache-tomcat-7.0.14&quot;.</p>

<p>If you don't have a utility program to unzip .zip files on your computer, you can download and install the free <a href="http://www.7-zip.org/">7-Zip</a> utility to easily zip and unzip files on your computer.</p>

<p>Now that you have unzipped the file into a convenient location, you should proceed to setup the environment variables.</p>

<h2>Step 4: Setup environmental variables</h2>

<p>Go to Start Menu -> Control Panel -> System. When the window opens up for the System settings, click the link to &quot;Advanced system settings&quot; as shown in the image below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/control-panel-advanced-system-settings.png" width="574" height="229" alt="Control Panel - Advanced system settings" title="Link to Advanced system settings in the Control Panel." />
	<div class="imagedesc">Control Panel - Advanced system settings</div>
</div>

<p>When the System Properties window opens, click the &quot;Environment Variables&quot; button as shown in the image below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/system-properties-window.png" width="426" height="474" alt="System Properties window" title="Click the Environment Variables button in the System Properties window." />
	<div class="imagedesc">System Properties window</div>
</div>

<p>Now click the &quot;New&quot; button in the Environment Variables window to add a new System variable:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/environment-variables-window.png" width="394" height="436" alt="Environment Variables window" title="The Environment Variables window." />
	<div class="imagedesc">Environment Variables window</div>
</div>

<p>Now enter the Variable name as &quot;JAVA_HOME&quot; and Variable value as &quot;C:\Program Files\Java\jdk1.6.0_25&quot; or whatever the complete path to the folder where your JDK was installed is, and press the OK button.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/adding-new-system-environment-variable.png" width="357" height="153" alt="New System Variable window" title="Adding new System variable." />
	<div class="imagedesc">New System Variable window</div>
</div>

<p>Now close all the open windows and proceed to start the Apache Tomcat server for the first time.</p>

<h2>Step 5: Start Apache Tomcat</h2>

<p>Now open Command Prompt and enter commands as shown in the image below to change directory to the bin folder of the Apache Tomcat's installation folder. On my computer, I unzipped the Apache Tomcat zip file in the &quot;C:\apache-tomcat-7.0.14&quot; folder.</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/starting-apache-tomcat-by-running-startup-command.png" width="677" height="392" alt="Start Apache Tomcat" title="Running the startup.bat command to start Apache Tomcat server." />
	<div class="imagedesc">Start Apache Tomcat</div>
</div>

<p>Once there, type the <code>startup</code> command and hit the Enter button to startup Apache Tomcat server for the first time on your computer.</p>

<pre>startup</pre>

<p>A new window pops up and shows the startup log of the Apache Tomcat server as shown in the image below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/apache-tomcat-server-startup.png" width="677" height="392" alt="Apache Tomcat starts up!" title="Apache Tomcat boots up for the first time." />
	<div class="imagedesc">Apache Tomcat starts up!</div>
</div>

<p>Now please open your browser and enter this address in the address field: <code>http://localhost:8080</code> and hit the Enter button to load the home page of your local Apache Tomcat server. You should see a home page with a message of success as shown in the image below:</p>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/apache-tomcat-successful-startup-homepage.png" width="610" height="360" alt="Home page of Apache Tomcat running on your computer" title="Visiting the home page of Apache Tomcat running on your computer." />
	<div class="imagedesc">Home page of Apache Tomcat running on your computer</div>
</div>

<p>Congratulations! You just finished installing and running Apache Tomcat 7.0 server for the first time on your computer.</p>

<h3>Play with the Servlet and JSP Examples</h3>

<p>You can click the &quot;Servlet Examples&quot; and &quot;JSP Examples&quot; links found on the home page of your local Apache Tomcat server to see the demos of live working Servlets and JSP pages.</p>

<h3>Shutting down Apache Tomcat</h3>

<p>To shut down Apache Tomcat, simply run this command while in the Apache Tomcat's <code>bin</code> directory:</p>

<pre>shutdown</pre>

<div class="imagefull">
	<img src="http://www.stardeveloper.com/images/shutdown-apache-tomcat.png" width="677" height="392" alt="Shut down Apache Tomcat" title="Shutting down Apache Tomcat server by running shutdown.bat command." />
	<div class="imagedesc">Shut down Apache Tomcat</div>
</div>

<p>Now you have a working copy of Apache Tomcat on your computer. Good luck with learning and developing JSP web applications!</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/tutorial/installing-apache-tomcat-7.0]]></guid>
<author>Faisal Khan</author>
<pubDate>Wed, 25 May 2011 00:00:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>An HTTP Module to redirect requests from root domain of your website to www subdomain</title>
<link><![CDATA[http://www.stardeveloper.com/articles/http-module-to-redirect-requests-from-root-domain-to-www-subdomain/]]></link>
<description><![CDATA[<h2>Introduction</h2>

<p>We will develop an <a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=1" title="Learn more about how HTTP modules work in ASP.NET">HTTP module</a> that will redirect all requests to non-www root domain name of your website, for example, stardeveloper.com, to www subdomain, for example, www.stardeveloper.com. You can also do the opposite and redirect all requests from www.yourwebsite.com to yourwebsite.com if you wish.</p>

<p>The redirection process will work by sending an HTTP 301 (permanent redirect) header to the browser. It is useful as the search engines and browsers will be able to give credence to the correct URL for your web page, that is, the ones with www. subdomain.</p>

<h2>Demonstration</h2>

<p>To demonstrate how this HTTP module works, let me make a request to the URL http://stardeveloper.com and see how it goes.</p>

<div class="image">
	<a href="http://www.stardeveloper.com/images/request-to-root-domain-of-stardeveloper.png"><img src="http://www.stardeveloper.com/images/request-to-root-domain-of-stardeveloper-thumbnail.png" width="300" height="120" border="0" alt="Sending a request to root domain of http://stardeveloper.com" /></a>
	<div class="imagedesc">Sending a request to root domain of Stardeveloper.com (http://stardeveloper.com)</div>
</div>

<p>My request gets redirected to http://www.stardeveloper.com.</p>

<div class="image">
	<a href="http://www.stardeveloper.com/images/redirected-to-www-subdomain.png"><img src="http://www.stardeveloper.com/images/redirected-to-www-subdomain-thumbnail.png" width="300" height="120" border="0" alt="The server redirects the request to http://www.stardeveloper.com" /></a>
	<div class="imagedesc">The server redirects the request to http://www.stardeveloper.com</div>
</div>

<p>Go ahead, try it yourself. Just enter <a href="http://stardeveloper.com">http://stardeveloper.com</a> in the URL field of your browser and hit 'enter' and see what happens.</p>

<h3>Explanation</h3>

<p>The HTTP module intercepted the request to the root domain of http://stardeveloper.com and redirected the browser to the www subdomain, http://www.stardeveloper.com.</p>

<p>I have set it up this way because I want Google to index my website as www.stardeveloper.com. Even though I can specify my preference in the Google webmaster tools panel, I still find it simple and elegant to keep all pages on my website with www.stardeveloper.com as the domain name.</p>

<p>Since all users who visit my website will see the www subdomain name of the website, I am pretty sure they will link to the pages with www subdomain in the URL as well.</p>

<div class="note">The HTTP module sends a '301 permanent redirect' header to the browser. It means that browser should always save the URL with the correct host name, that is, www.stardeveloper.com, in its history, favorites, and other records. The same applies to search engines, who will always index my website with www subdomain name.</div>

<h2>Uses</h2>

<p>You can use this HTTP module to:</p>

<ul>
<li>Redirect users from non-www host name of your website to a www. host name.
	<p>For example, you can redirect all requests to http://yourwebsite.com to http://www.yourwebsite.com and vice versa.</p></li>
<li>You can redirect .net and .org requests for your domain aliases to your .com domain name.
	<p>This scenario is useful if you are also using .net and .org domain names like http://www.yourwebsite.net and http://www.yourwebsite.org and you want those domains to redirect to your website's .com domain name like http://www.yourwebsite.com.</p>
	<p>At Stardeveloper, I also have registered http://www.stardeveloper.net and http://www.stardeveloper.org domain names. I use this module to redirect all requests to those domain names to http://www.stardeveloper.com.</li>
<li>If you are moving your website from one host name to another then you can redirect all requests sent to previous host name to the new one.
	<p>For example, you can set this module to redirect all requests to http://www.youroldwebsite.com to http://www.yournewwebsite.com.</p></li>
</ul>

<h2>Root domain vs www subdomain</h2>

<p>The domain name for <a href="http://www.stardeveloper.com/">Stardeveloper</a> is <i>stardeveloper.com</i>. Most users think that a root domain name is synonymous with www subdomain of a website. This actually is not technically true as root domain name and www subdomain can point to two different IP addresses/websites. But for end users' perspective, they think that with or without the www in the host name, the request should go to the same website. So in case of Stardeveloper, typing http://stardeveloper.com should lead to the same home page as http://www.stardeveloper.com does.</p>

<p>With that said, you should have one policy for the links on your website. I will recommend not switching back and forth between www and non-www links on your website pages. Keep a consistent theme and force it using this HTTP module.</p>

<h2>Examples of websites with preference for root vs www subdomain</h2>

<p>To give you example of how real-World websites are using this technique, I will give examples of two popular social networking websites that have a preference for non-www and www subdomains in their host names.</p>

<h3>Twitter</h3>

<p>Twitter strongly forces the URL to use the shorter version of the host name for their website. If you type http://www.twitter.com, you will be redirected to http://twitter.com.</p>

<h3>Facebook</h3>

<p>Facebook on the other hand uses the full www subdomain for the pages on its website. Go and type http://facebook.com in your URL field of your browser and you will be redirected to http://www.facebook.com.</p>

<p>You can choose either of the two themes for your website. Whichever you choose, the decision is yours, but just select one and use it consistently.</p>

<h2>How will domain redirection work?</h2>

<p>Let me give you a quick overview of how the domain redirection process works.</p>

<p>When a user requests a page, the request gets intercepted by our <code>DomainRedirectorModule</code> HTTP module. It checks the host name of the URL.</p>

<div class="note"><code>Host</code> name is the part of the URL containing the full domain or subdomain of the website. For example, in the link http://www.stardeveloper.com/articles/convert-ip-address-to-long/, <i>www.stardeveloper.com</i> is the host name.</div>

<p>Now, if the host name of the URL matches the non-www version of the host name of our website, for example, <i>stardeveloper.com</i>, it will redirect the full request including the path and query information associated with the URL to <i>www.stardeveloper.com</i>. Thus a request like http://stardeveloper.com/articles/convert-ip-address-to-long/?ref=whatever gets redirected to <i>http://<b>www.</b>stardeveloper.com/articles/convert-ip-address-to-long/?ref=whatever</i>.</p>

<p>And like I said before, the HTTP module will send 301 HTTP header to tell to the browser, search engine or whoever the client is to <i>permanently</i> redirect the request. This means that we are telling the client that previous URL is no more accessible and you should update the reference from the old URL to the new one.</p>

<h2>Developing the DomainRedirector HTTP module</h2>

<p>Let us now look at the code of the HTTP module we talked above so that you can create this module on your computer and use it on your website straightaway.</p>

<h3>Code</h3>

<p>Create a new text file and save it as <code>Stardeveloper.Modules.DomainRedirectorModule.cs</code> in the /App_Code folder of your ASP.NET application. Then copy/paste following code in it:</p>

<pre>
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Web;

namespace Stardeveloper.Modules
{
    public class DomainRedirectorModule : IHttpModule
    {
        const string FromHostName = &quot;stardeveloper.com&quot;;
        const string ToHostName = &quot;www.stardeveloper.com&quot;;
        
        public void Init(HttpApplication app)
        {
            app.BeginRequest += new EventHandler(app_BeginRequest);
        }

        protected void app_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            Uri currentUri = app.Request.Url;

            if (currentUri.Host == FromHostName)
            {
                Uri redirectToUri = new Uri(new Uri(&quot;http://&quot; + ToHostName), currentUri.PathAndQuery);
                
                RedirectPermanently(app.Response, redirectToUri.ToString());
            }
        }
        
        public static void RedirectPermanently(HttpResponse res, string location)
        {
            // Permanent redirection
            res.Status = &quot;301 Moved Permanently&quot;;
            res.AddHeader(&quot;Location&quot;, location);
            res.Flush();
            res.End();
        }

        public void Dispose()
        {
        }
    }
}</pre>


<h3>Explanation</h3>

<p>It is a pretty straight forward HTTP module actually. If you have read the <a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=1" title="Introduction to developing HTTP modules in ASP.NET">introduction to developing HTTP modules</a>, the code here shouldn't be too difficult to understand.</p>

<p>Anyhow, the first thing we do is to import namespaces that we will be using in our code later.</p>

<pre>
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Web;
</pre>

<p>Next we specify the namespace for our HTTP module.</p>

<p>Our <code>DomainRedirectorModule</code> class implements the <code>IHttpModule</code> interface. We have to do that if we want our <code>DomainRedirectorModule</code> class to work as an HTTP module.</p>

<pre>
namespace Stardeveloper.Modules
{
    public class DomainRedirectorModule : IHttpModule
    {
        ...
    }
}
</pre>

<p>Two constants are used to set the <i>from</i> and <i>to</i> host names of our website.</p>

<p>Here we are using straight string matches. You can improve this code to use regular expressions to match from and to domains and sub domains.</p>

<pre>
const string FromHostName = &quot;stardeveloper.com&quot;;
const string ToHostName = &quot;www.stardeveloper.com&quot;;</pre>

<p><code>Init()</code> method is called by ASP.NET runtime to allow our HTTP module to select events in the <a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=2">HTTP request handling pipeline</a> that it wants to handle.</p>

<p>Here, we simply handle the <code>BeginRequest</code> event. This event is the first event in HTTP request handling pipeline. Handling this event means that we can redirect the user straight from the surface of our web application and not letting the request pass deeper into HTTP request handling pipeline.</p>

<pre>
public void Init(HttpApplication app)
{
	app.BeginRequest += new EventHandler(app_BeginRequest);
}</pre>

<p>Right, now we get into the main method that checks the host name and redirects the user if necessary.</p>

<p>We do a direct string comparison using the <code>==</code> operator in C#. If two strings match, we get a <code>true</code> value back, that is, we are given a green pass to step down into the code in the brackets.</p>

<p>Assuming we have a match for the host name requested by the user to the host name that we have in the <code>FromHostName</code> constant, we create a new <code>Uri</code> object using a constructor that takes two arguments. The first arguments is the <code>Uri</code> of the <i>base</i> host name of the URL and the second argument is the <i>path and query</i> part of the destination URL.</p>

<p>This way, all requests to pages deeper in the website with query string parameters in them, like http://stardeveloper.com/articles/display.html?article=2009071801&amp;page=2, get redirected to a URL with the same path and query, like http://<b>www.</b>stardeveloper.com/articles/display.html?article=2009071801&amp;page=2.</p>

<p>Finally, we redirect the user to the destination URL.</p>

<pre>
protected void app_BeginRequest(object sender, EventArgs e)
{
	HttpApplication app = sender as HttpApplication;
	Uri currentUri = app.Request.Url;

	if (currentUri.Host == FromHostName)
	{
		Uri redirectToUri = new Uri(new Uri(&quot;http://&quot; + ToHostName), currentUri.PathAndQuery);
                
		RedirectPermanently(app.Response, redirectToUri.ToString());
	}
}
</pre>

<p>We use a utility method with the name of <code>RedirectPermanently()</code> to send 301 header to the browser to redirect the request to the destination URL.</p>

<p>In practice, I keep methods like this in other utility classes and not in the HTTP module like I am doing in the code here. I have copied the method here only to keep things simple to understand for you.</p>

<pre>
public static void RedirectPermanently(HttpResponse res, string location)
{
	// Permanent redirection
	res.Status = &quot;301 Moved Permanently&quot;;
	res.AddHeader(&quot;Location&quot;, location);
	res.Flush();
	res.End();
}
</pre>

<p>Well, this is just about it as far as the code is concerned. The code is so clean that it shouldn't take you much time to understand how we are handling domain redirection.</p>

<h3>Installation</h3>

<p>To install this HTTP module in your ASP.NET web application, open your root web.config file and add following bit of configuration data in the configuration/system.webServer/modules node:</p>

<pre>
&lt;configuration&gt;
    ...

    &lt;system.webServer&gt;
        &lt;modules&gt;
            &lt;add name=&quot;DomainRedirectorModule&quot; type=&quot;Stardeveloper.Modules.DomainRedirectorModule&quot;/&gt;
        &lt;/modules&gt;
    &lt;/system.webServer&gt;
&lt;/configuration&gt;
</pre>

<p>Now your HTTP module is ready to start redirecting the requests.</p>

<h2>Summary</h2>

<p>In this tutorial, we learned how to develop an HTTP module to sit on top of our ASP.NET web application and redirect requests to www or non-www host names, as we desire, of our website. We also learned that we can use the module to redirect requests from .net and .org domain names of our website to .com domain name. We can use the same technique to redirect requests from old host name to a new one. This may come very handy when moving content from an old website to a new one.</p>

<h3>Join me</h3>

<p>Well there you have it guys, another article with code and explanation to help you solve real-World problems, add features, and improve web application design and performance on your website.</p>

If you like this article then please <a href="#bookmark">join my email list</a> using the links below and I'll send you new articles I publish by email. You won't even have to visit this website if you don't want to. You can even visit my <a href="http://www.facebook.com/Stardeveloper">Facebook page</a> and <i>like</i> it to connect with me, or should I put it better, to keep a tap on what I up to. If you want to connect with me personally, you can also <a href="http://www.facebook.com/Faisal.Khan.Stardeveloper">add me as friend on Facebook</a> if you have interest in web development, analytics, A/B testing, technology, blogging, etc. I like that kind of stuff and we'll do well if you have at least some interest in those fields. :)</p>

<p>If you are interested in writing for Stardeveloper.com, then please add me as a friend on Facebook and then message me on what you want to write about. If you need advice, or have a question, then that my just be the right place to ask that.</p>

<p>I wish you all the success! See you in another article.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/http-module-to-redirect-requests-from-root-domain-to-www-subdomain/]]></guid>
<author>Faisal Khan</author>
<pubDate>Sun, 02 Jan 2011 21:08:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>How Stardeveloper.com achieved 120% improvement in website load time?</title>
<link><![CDATA[http://www.stardeveloper.com/articles/how-stardeveloper-achieved-120-percent-improvement-in-website-load-time/]]></link>
<description><![CDATA[<p>Back in November 2009, I visited the 'Site Performance' section in Google webmaster tools and was astonished to see that it was taking on average 8.6 seconds for a page to load on Stardeveloper.com. Google also further commented on it by saying that my website was slower than 90% of the websites on the internet. I was taken aback.</p>

<div>
	<a href="http://www.stardeveloper.com/blog/images/stardeveloper-webmaster-tools-performance-overview.png"><img src="http://www.stardeveloper.com/images/stardeveloper-webmaster-tools-performance-overview-cropped.png" width="600" height="172" border="0" alt="Performance overview of load time at Stardeveloper.com before enabling ASP.NET static resource caching" /></a>
	<div class="imagedesc">Pages took 8.6 secs on avg. to load before enabling ASP.NET static resource caching</div>
</div>

<p>I read everything I could find on caching, website performance, HTTP headers, delay loading of JavaScripts, etc., to improve the loading time of my website. It was only after I came to know about setting HTTP <code>Expires</code> and <code>Cache-Control: max-age</code> headers that I decided to set them up on my website. The results were nothing short of awesome. As you can see in the chart below, the average load time had improved to 3.9 seconds.</p>

<div>
	<a href="http://www.stardeveloper.com/images/load-time-improvement-using-static-resource-caching.png"><img src="http://www.stardeveloper.com/images/load-time-improvement-using-static-resource-caching-cropped.png" width="600" height="146" border="0" alt="Chart displays load time improvement achieved at Stardeveloper.com using ASP.NET static resource caching" /></a>
	<div class="imagedesc">Pages now take on avg. 3.9 secs to load after enabling ASP.NET static resource caching</div>
</div>

<p>In the rest of this article I talk about how I did it on my ASP.NET website, and what I learned along the way and how you can implement it on yours.</p>

<h2>Website Performance</h2>

<p>While the importance of caching items accessed from the database in ASP.NET pages remains the same, we have come to know that it is only 20% of the perceived performance that the end-user gets. For them, if a website has plenty of JavaScript files, iframes, ads, images and multiple CSS files, the pages will take a long time to load no matter what you do at the <i>backend</i>.</p>

<p>Website performance is an area which is coming more and more in limelight these days. Most of the work nowadays is being done at improving and optimizing the front-end of the website. This is where 80% of the perceived performance of a website for an end-user exists. There are many things that can be done to improve the load time but one thing that we, as ASP.NET developers, can do in just a few minutes of our time and which can have a huge effect in improving the load time of our website is to <a href="http://www.stardeveloper.com/articles/expires-and-max-age-headers-in-aspnet/" title="Learn more about static resource caching for ASP.NET websites">enable static resource caching</a> for our ASP.NET pages.</p>

<h3>What are static resources?</h3>

<p>Static resources are CSS, JavaScript, images, videos and zip files that reside on our web server. We can tell IIS, our ASP.NET pages run on, to send one of the two standard HTTP headers, <a href="http://www.stardeveloper.com/articles/expires-and-max-age-headers-in-aspnet/" title="Expires and Cache-Control: max-age explained in detail">Expires or Cache-Control: max-age</a>, to the client browser every time a static resource is requested on our server. These headers will tell the browser to <i>cache</i> these items on its local hard drive for a long period of time, thus cutting the need to request them from our server again and again.</p>

<p>If you want to enable static resource caching in your ASP.NET website, then you should check out my introduction to <a href="http://www.stardeveloper.com/articles/expires-and-max-age-headers-in-aspnet/" title="Introduction to Expires and Cache-Control: max-age headers and how to set them on your website">Expires and Cache-Control: max-age</a> headers. If you are an ASP.NET developer then you cannot absolutely afford to not read that article. It only takes a couple of minutes to edit your web.config file and your website will see dramatic improvement in load time.</p>

<p>Stay tuned, I will now share with you exactly where my website, <a href="http://www.stardeveloper.com/" title="Stardeveloper.com">Stardeveloper.com</a>, stood one year back and what effect enabling static resource caching had on its load time. All the stats I refer to in this article are from Google webmaster tools. Trust me, you will be surprised to see the results.</p>

<h2>Why I felt there was a need to improve website load time at Stardeveloper.com?</h2>

<p>Let me start by saying that late last year (2009), I noticed that <a href="http://blog.stardeveloper.com/post/334425197/stardeveloper-slower-than-majority-of-websites" title="A one year old blog post in which I talk about the slow load time at Stardeveloper.com">pages at Stardeveloper took an average of 8.6 seconds to load</a>. I came to know this after checking my website's load time in <a href="http://www.google.com/webmasters/tools/" title="Google webmaster tool">Google webmaster tools</a>.</p>

<div>
	<a href="http://www.stardeveloper.com/blog/images/stardeveloper-webmaster-tools-performance-overview.png"><img src="http://www.stardeveloper.com/images/stardeveloper-webmaster-tools-performance-overview-cropped.png" width="600" height="172" border="0" alt="Performance overview of load time at Stardeveloper.com before enabling ASP.NET static resource caching" /></a>
	<div class="imagedesc">Pages took 8.6 secs on avg. to load before enabling ASP.NET static resource caching</div>
</div>

<p>That chart took me by surprise. I was shocked and saddened to see that my website was slower than 90% of the websites on the Internet. I didn't see the bright side of it. I mean making a website slower than 90% of the websites on the Internet is quite an achievement in itself. Right? LOL! No kidding, I was very disappointed.</p>

<p>What I did was that I began to change the design and layout of Stardeveloper.com. You can see the new design and layout in the new articles that have been published this year (2010). This article that you are reading is using the new theme. You may not notice it but the pages in the new layout are quite optimized to load fast in your browser.</p>

<p>But just making the new articles load quicker wouldn't do the trick for my website. There are hundreds of old articles and forum posts compared to which the new articles don't yet make 1% of the content. So what to do?</p>

<h3>HTTP caching, headers and website performance</h3>

<p>I began to read about HTTP caching, headers, website performance, and load time improvement tips from the experts. One thing that struck me immediately was the effect of using HTTP <code>Expires</code> and <code>Cache-Control: max-age</code> headers. They did not need an ETag to be sent for the file. They made sense to me the moment I read about them.</p>

<p>Now that I knew about <code>Expires</code> and <code>Cache-Control: max-age</code> headers, I needed to implement them on my website. I had two options:</p>

<ol>
<li>Develop an <a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=1" title="Introduction to HTTP modules for ASP.NET developers">HTTP module</a> and then each time a static resource was being sent to the browser, I should set one of these two headers using <code>HttpResponse.Cache.SetExpires()</code> for <code>Expires</code> and <code>HttpResponse.Cache.SetMaxAge()</code> for <code>Cache-Control: max-age</code>, methods, each time that resource is requested.
<p>The problem was that I had to manually check the file that was being sent to the browser to see if it was a static file or a dynamic file. While it was still not difficult, there was an easier option available.</p>
</li>
<li>Edit web.config file and add few lines to tell the IIS to send <code>Expires</code> or <code>Cache-Control: max-age</code> headers for all static resources on the website.</li>
</ol>

<p>The moment I came to know that these headers can be enabled just by editing the web.config file, I immediately updated the web.config file for my website. I used <code>Cache-Control: max-age</code> header because it allowed me to set a <i>relative</i> date and time in the future. You can learn more about <a href="http://www.stardeveloper.com/articles/expires-and-max-age-headers-in-aspnet/" title="Learn how to set Expires or Cache-Control: max-age header by adding a few lines in web.config file">Expires and Cache-Control: max-age</a> headers and how to set them using web.config file by visiting that article.</p>

<p>Once I had made the changes, I crossed my fingers and waited to see how my website's load time improves in the time to come.</p>

<h2>120% improvement in website load time at Stardeveloper.com after enabling ASP.NET static resource caching</h2>

<p>After making the changes in the web.config file to enable static resource caching using <code>Cache-Control: max-age</code> header, my website's load time slowly began to improve, that is, it began to took less and less time for the web pages to load at Stardeveloper.com.</p>

<p>I was so deligted that I wanted to share this information with my website visitors. This <a href="#tableofcontents">series of articles</a> took inspiration from the very same fact. Here is the latest image taken from Google webmaster tool's site performance page:</p>

<div>
	<a href="http://www.stardeveloper.com/images/load-time-improvement-using-static-resource-caching.png"><img src="http://www.stardeveloper.com/images/load-time-improvement-using-static-resource-caching-cropped.png" width="600" height="146" border="0" alt="Chart displays load time improvement achieved at Stardeveloper.com using ASP.NET static resource caching" /></a>
	<div class="imagedesc">Pages now take on avg. 3.9 secs to load after enabling ASP.NET static resource caching</div>
</div>

<p>As you can see, it is now taking only <i>3.9 seconds</i> for a page to load on average at Stardeveloper.com as compared to 8.6 seconds it was taking just an year back. A massive improvement of more than 120%, isn't it?</p>

<h3>Conclusion</h3>

<p>In this article, we learned how Stardeveloper.com got an improvement in load time from using static resource caching by big order of magnitude. We saw the technique and learned how we can implement it on our websites.</p>

<p>Considering the fact that <a href="http://blog.stardeveloper.com/post/334432830/page-load-speed-may-be-a-factor-in-deciding-page-rank-at" title="News: Page load time may be a deciding factor in rankings of a website on Google">page speed may be a deciding factor in ranking a website on Google</a>, improvement in load time was a welcome change. Not only it leads to improvement in page ranking on Google, it leads to a decrease in bounce rate of visitors reading articles on your website as well.</p>

<p>That's it fellows! I hope you found the article inspiring. These are true stats of a website which is a living example of how much an effect one can achieve in load time improvement using HTTP caching headers. Please set them up on your website, and if you already have, share your stats in comments below.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/how-stardeveloper-achieved-120-percent-improvement-in-website-load-time/]]></guid>
<author>Faisal Khan</author>
<pubDate>Sun, 26 Dec 2010 12:41:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>Display Dzone voting button on your website only to visitors referred form Dzone.com</title>
<link><![CDATA[http://www.stardeveloper.com/articles/display-dzone-voting-button-on-your-website-only-to-visitors-from-dzone/]]></link>
<description><![CDATA[<p>The title of this article says it all. You will learn <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">how to tag all Dzone visitors</a>, using a small cookie, who visit your website by following a link on <a href="http://www.dzone.com">Dzone.com</a> that links to your website. Once that cookie is placed in the user's browser, we will be able to identify visitors from Dzone.com on all visits to your website from then onwards. That cookie will be read by a piece of code on your website which will display Dzone voting button to these users. Dzone voting button will serve to increase the votes your website receives from Dzone users, leading to even more visits and page views for your website.</p>

<p>The code for this application was developed in C# and it works on all websites running ASP.NET 3.0 and above. We have already developed the complete application, <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">Referring Domain Tagger Application</a>. You can learn more about <a href=" http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">tagging</a> and how you can use it to display buttons, badges and widgets on your website for all the cool social networking and bookmarking websites out there like Facebook, Twitter and Dzone, only to users referred from them.</p>

<h2>Displaying Dzone voting button to Dzone users at Stardeveloper.com</h2>

<p>Following couple of images show how an article on Stardeveloper.com shows Dzone button to a visitor referred (and thus tagged) from Dzone.com:</p>

<div class="image">
	<a href="http://www.stardeveloper.com/images/displaying-article-to-an-untagged-user.png"><img src="http://www.stardeveloper.com/images/displaying-article-to-an-untagged-user-thumbnail.png" width="300" height="190" border="0" alt="No Dzone voting button for other users of Stardeveloper.com" /></a>
	<div class="imagedesc">No Dzone voting button for other users of Stardeveloper.com<br />
	(click the image to view in full size)</div>
</div>

<div class="image">
	<a href="http://www.stardeveloper.com/images/displaying-dzone-badge-only-to-a-dzone-tagged-user.png"><img src="http://www.stardeveloper.com/images/displaying-dzone-badge-only-to-a-dzone-tagged-user-thumbnail.png" width="300" height="190" border="0" alt="No Dzone voting button for other users of Stardeveloper.com" /></a>
	<div class="imagedesc">Dzone voting button being shown to a visitor from Dzone.com<br />
	(click the image to view in full size)</div>
</div>

<p>Although Dzone doesn't need an introduction because it is a very popular developer website, I will provide a short introduction to it and its cool voting system and then I will give you a practical example of how this works (and is working on Stardeveloper.com) with images and live demonstration.</p>

<h2>What is Dzone and how does its voting system work?</h2>

<p>Dzone is a website targeted towards developers. The 'D' in Dzone stands for 'Developers'. You can call Dzone as 'Developers Zone' if you want. It is open for all people to submit links to news, articles and blog posts of interest to developers. Depending on the relevance and quality of the content, that link is voted up or down. Any Dzone user can cast his vote for any link submitted on Dzone. Once a link gets more and more votes, it gets promoted on their website. The more that link receives votes, the more it says live on their website. The more live it remains, the more clicks that link receives.</p>

<h2>Why should every developer website have a Dzone voting button?</h2>

<p>If you are a developer and have a website or a blog on topics related to programming languages, databases, or web development in general, your website will benefit from having a Dzone voting button on it. You should also register for a free user account at Dzone and post links to your articles and blog posts as you publish them.</p>

<h2>Why use Referring Domain Tagger Application?</h2>

<p>To prevent loading of Dzone JavaScript file for every user of your website, the majority of which may be other users, you should use <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">Referring Domain Tagger Application</a> to only display Dzone voting button to users of Dzone.com.</p>

<p>You can use similar logic to load IFrame and JavaScript files for buttons, badges and widgets of other bookmarking websites without compromising the load time of your web pages by using this application.</p>

<h2>Live example of Referring Domain Tagger Application working on Stardeveloper.com</h2>

<p>If you are a Dzone user, you would already have seen a Dzone voting button at the top of this article. That button was displayed because you were tagged, that is, a cookie was placed on your browser by an <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">HTTP module</a> installed on this website when you clicked a link on Dzone and visited Stardeveloper.com. Then an ASP.NET <a href="http://www.stardeveloper.com/articles/tagged-domain-matcher-control/">custom web server control</a> was used to read that tag and display a Dzone voting badge to you.</p>

<p>You can learn more about the different components of this application by reading the <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">introduction to this application</a> and following the step by step one-by-one from there.</p>

<p>If you are not a Dzone user then you would not have seen a Dzone voting button on this article. Don't worry, I'll make it pop up for you. :)</p>

<p>Go to <a href="http://www.dzone.com">Dzone</a> and enter 'Stardeveloper.com' in the search field and press the 'Submit' button. Here is a direct link to search results showing <a href="http://www.dzone.com/links/search.html?query=stardeveloper.com&amp;x=10&amp;y=7">articles from Stardeveloper.com</a>. Next, click the first article that comes up in the search results. You will be redirected to an article on Stardeveloper.com. This time there will be a Dzone voting button shown at the top of that article. Simple!</p>

<p>Next, close your browser window. Now reopen it and visit <a href="http://www.stardeveloper.com">Stardeveloper.com</a> and navigate to any article on it. You can visit <a href="http://www.stardeveloper.com/articles/display-dzone-voting-button-on-your-website-only-to-visitors-from-dzone/">this same article you are reading</a> if you want. There will be a shining Dzone voting button waiting for you to vote up. :)</p>

<div class="note">Please don't forget to vote up this article if you found it useful. You can also share this application on Twitter and Facebook. The links are shown at the top of the article. I'll appreciate it very much!</div>

<h2 id="code-example">The code for Dzone voting button</h2>

<p>If you have followed the <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">development of this application</a> from the beginning, you'll be knowing that the two most important components of this application are <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> HTTP module and <a href="http://www.stardeveloper.com/articles/tagged-domain-matcher-control/">TaggedDomainMatcherControl</a> custom web server control. I'll show just the code that I put on my ASP.NET pages that display articles at Stardeveloper.com for Dzone voting button using the <code>TaggedDomainMatcherControl</code>.</p>

<p>This is the only piece of code required to display Dzone voting button to Dzone users in your ASP.NET pages:</p>

<pre>
...

&lt;%@ Register TagPrefix=&quot;sd&quot; Namespace=&quot;Stardeveloper.Controls&quot; %&gt;

...

&lt;sd:TaggedDomainMatcherControl DomainToMatch=&quot;dzone.com&quot; runat=&quot;server&quot;&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	var dzone_url = '';
	var dzone_title = '';
	var dzone_blurb = '';
	var dzone_style = '1';
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://widgets.dzone.com/links/widgets/zoneit.js&quot;&gt;&lt;/script&gt;
&lt;/sd:TaggedDomainMatcherControl&gt;

...</pre>

<p>You can see clearly how simple this custom web server control, <code>TaggedDomainMatcherControl</code>, makes our job of displaying the Dzone voting button. Whatever text you enclose inside this control gets displayed to the user <i>only</i> if he has been tagged by the <code>ReferringDomainTaggerModule</code> HTTP module. In this case, the text was the HTML and JavaScript code to display Dzone voting button.</p>

<h2>Summary</h2>

<p>In the multipart tutorial, we learned how a small cookie can be placed in a user's browser visiting our website from a link on another website. That cookie's value can be the domain name of the referring website. We called it <i>tagging</i> the user. We created an HTTP module and placed the code to scan for referring links and cookies in it. To tag users from only a small number of websites, we listed the domain names to tag in the web.config file. We then created a custom web server control and inserted it in ASP.NET pages where we wanted to display site specific code only to users of a given a domain name. An example of which we saw in this article.</p>

<p>Please read this tutorial from the beginning to learn <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">tagging</a> and understand <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">how this application works</a>, and how you can port this application to other web development platforms.</p>

<p>That's it friends, please share this application with others who you think might benefit from it. Spread the good word as they call it. I'll begin development on another application now and will post it on this website when I have finished it. So if you feel like, you can bookmark this website using the links below. Have a good day!</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/display-dzone-voting-button-on-your-website-only-to-visitors-from-dzone/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 06 Dec 2010 08:26:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>A custom web server control to display site specific content to Facebook, Twitter, and Dzone users</title>
<link><![CDATA[http://www.stardeveloper.com/articles/tagged-domain-matcher-control/]]></link>
<description><![CDATA[<p>We will create a custom ASP.NET web server control that will read the tag (a cookie set by <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> HTTP module) and the referring link to identify the user to our website as a user coming from a social network or bookmarking site like Facebook, Twitter or Dzone. Once the use is identified, the content within the control will be rendered to the user to display social bookmarking and sharing links and badges.</p>

<p>This custom web server control is a part of <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">Referring Domain Tagger Application</a>. Learn more about <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">tagging</a> and the <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">purpose of this application</a> by reading the first few pages.</p>

<h2>How will this control work?</h2>

<p>This is a custom web server control that you will use to encapsulate code that you want only to be rendered to users coming from social networks or bookmarking websites. An example of a code that you can use to say &quot;Hi&quot; to Dzone users is shown below:</p>

<pre>
&lt;%@ Register TagPrefix=&quot;sd&quot; Namespace=&quot;Stardeveloper.Controls&quot; %&gt;

&lt;sd:TaggedDomainMatcherControl DomainToMatch=&quot;dzone.com&quot; runat=&quot;server&quot;&gt;
	&lt;p&gt;Hi Dzone user!&lt;/p&gt;
&lt;/sd:TaggedDomainMatcherControl&gt;</pre>

<p>We first register our <code>Stardeveloper.Controls</code> namespace using the tag prefix, &quot;sd&quot;.</p>

<p>To access the control, we write down the name of our <code>TaggedDomainMatcherControl</code> class after the tag prefix and colon. There are two attributes in this control. <code>DomainToMatch</code> should contain the domain name to match. <code>runat</code> is mandatory and its value is almost always &quot;server.&quot;.</p>

<p>The encapsulated bit of code will only be rendered if the user has been tagged, that is, have visited our website from Dzone.com. You can replace 'dzone.com' with 'facebook.com' to render site specific content to Facebook users. What you can do with this control is only limited by your imagination and creativity.</p>

<h2>Stardeveloper.Controls.TaggedDomainMatcherControl.cs</h2>

<p>Open a new file in Notepad or Visual Studio and save it as 'Stardeveloper.Controls.TaggedDomainMatcherControl.cs' in the /App_Code folder of your ASP.NET website. Now copy and paste following code in it and then hit the 'Save' button:</p>

<pre>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using Stardeveloper.Modules;

namespace Stardeveloper.Controls
{
  public class TaggedDomainMatcherControl : Control
  {
    public virtual string DomainToMatch { get; set; }

    protected override void Render(HtmlTextWriter writer)
    {
      if (String.IsNullOrEmpty(DomainToMatch))
        throw new ArgumentNullException(&quot;Please set the DomainToMatch attribute to a valid domain name. Empty domain names are not accepted.&quot;);

      HttpRequest req = Page.Request;
      HttpCookie ck = req.Cookies[ReferringDomainTaggerModule.CookieName_TaggedDomains];
      Uri referrer = req.UrlReferrer;

      if ((ck != null &amp;&amp; ck.Value.IndexOf(DomainToMatch, StringComparison.OrdinalIgnoreCase) != -1) ||
        (referrer != null &amp;&amp; referrer.Host.IndexOf(DomainToMatch, StringComparison.OrdinalIgnoreCase) != -1))
        base.Render(writer);

      req = null;
    }
  }
}</pre>

<p>If you have saved the file, you are now ready to move to the next step to <a href="http://www.stardeveloper.com/articles/configuring-and-running-referring-domain-matcher-application/">configure the web.config file</a>. There are now no more files to be created.</p>

<p>If you want to understand the inner working of this control, then please continue reading this article as explanation follows next.</p>

<h2>Explanation</h2>

<p>We import the necessary namespaces. <code>Stardeveloper.Modules</code> namespace is required to properly reference <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> HTTP module.</p>

<pre>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using Stardeveloper.Modules;</pre>

<p>Next, we will place this custom web server control inside <code>Stardeveloper.Controls</code> namespace.</p>

<pre>
namespace Stardeveloper.Controls
{
	...
}</pre>

<p>To work as a web server control, our class has to extend <code>Control</code> class.</p>

<pre>
public class TaggedDomainMatcherControl : Control
{
	...
}</pre>

<p><em>Any <code>public virtual</code> properties declared in a custom web server control automatically become attributes</em>. As we saw in the code example above, you can set the <code>DomainToMatch</code> property by setting the attribute of this control in your ASP.NET page to &quot;facebook.com&quot;. We'll see another working example of this piece of code later.</p>

<pre>
public virtual string DomainToMatch { get; set; }</pre>

<p>Next, we override the <code>Render()</code> method. In this method we'll do the checking for the cookie and referring link.</p>

<pre>
protected override void Render(HtmlTextWriter writer)
{
	...
}</pre>

<p>The first thing we do within this method is to check for <code>DomainToMatch</code> property. If you have not explicitly set this attribute in your ASP.NET page, an exception will be thrown to alert you to the fact that you have forgotten to specify the domain name to match.</p>

<pre>
if (String.IsNullOrEmpty(DomainToMatch))
  throw new ArgumentNullException(&quot;Please set the DomainToMatch attribute to a valid domain name. Empty domain names are not accepted.&quot;);</pre>

<p>We save references to current <code>HttpRequest</code> object, our <code>&quot;SD_TaggedDomains&quot;</code> cookie, and referring <code>Uri</code> for this page in local variables.</p>

<pre>
HttpRequest req = Page.Request;
HttpCookie ck = req.Cookies[ReferringDomainTaggerModule.CookieName_TaggedDomains];
Uri referrer = req.UrlReferrer;</pre>

<p>We check for the presence of <code>DomainToMatch</code> domain name in the <code>Value</code> of the cookie. Next, we check for the referring <code>Uri</code> for the presence of <code>DomainToMatch</code> domain name in its host name. If either of these two conditions is met, we render the enclosed content to the user.</p>

<pre>
if ((ck != null &amp;&amp; ck.Value.IndexOf(DomainToMatch, StringComparison.OrdinalIgnoreCase) != -1) ||
  (referrer != null &amp;&amp; referrer.Host.IndexOf(DomainToMatch, StringComparison.OrdinalIgnoreCase) != -1))
  base.Render(writer);</pre>

<p>This is it as far as this control is concerned. Now, please move to the next page to <a href="http://www.stardeveloper.com/articles/configuring-and-running-referring-domain-tagger-application/">configure and to run this application</a>.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/tagged-domain-matcher-control/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 06 Dec 2010 08:24:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>Displaying statistics logged by our HTTP module</title>
<link><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-module-stats-aspx/]]></link>
<description><![CDATA[<p>The <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> is an HTTP module to tag users visiting your website who follow a link from another website by placing a small cookie in the user's browser to identify them later. This module works silently to tag only the users which are being referred from the domain names in the list of domain names to be tagged. You can add or remove domain names to this list very easily. This module is a component of <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">Referring Domain Tagger Application</a>. The purpose of this application is to tag users coming from websites like Facebook, Twitter and Dzone and then to show these visitors site specific content.</p>

<p>To visitors visiting from social networks or bookmarking sites, you can be more liberal in displaying social bookmarklets and 'Like/Share/Recommend/Retweet/Vote' buttons as compared to visitors who are accessing your website directly or through a search engine. This application is designed to make this all very easy for you.</p>

<p>So far, we have learned about <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">tagging users using cookies and how it works</a>, have got a good <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">overview of the application</a>, and have developed the first and most important component of this application: <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> - which is an HTTP module. Now we are going to make an ASP.NET page to display some statistics to the administrator of this application, that is you for your website. These stats are collected by the <code>ReferringDomainTaggerModule</code>.</p>

<p>As administrator of your <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">Referring Domain Tagger Application</a>, you'll want to see if the tagging is being done correctly or not and secondly, if you can see some stats to figure out which domain's referred users are being tagged more often and which domain's, less. We will develop an ASP.NET page to pull statistics from <code>ReferringDomainTaggerModule</code> and display them in a tabular fashion to do just that.</p>

<p>One thing that I have talked previously and I mention it here again is that these stats are only kept from the time this ASP.NET application was started in IIS. As soon as the application restarts (for example, when you edit web.config file) or when IIS is restarted, the stats are reset. I did not deliberately add the complexity of storing and retrieving these stats from the database. You are free to modify the code to have this module store its stats in the SQL Server database and make this ASP.NET page show those stats from there.</p>

<h2>Sample stats</h2>

<p>Following image shows sample stats as they will be displayed by this ASP.NET page:</p>

<div class="image">
	<a href="http://www.stardeveloper.com/images/referring-domain-tagger-module-stats-aspx.png">
	<img src="http://www.stardeveloper.com/images/referring-domain-tagger-module-stats-aspx-thumbnail.png" width="300" height="163" alt="Sample stats from ReferringDomainTaggerModuleStats.aspx" border="0" /></a>
	<div class="imagedesc">Sample stats from ReferringDomainTaggerModuleStats.aspx<br />
	(click the image to view in full size)</div>
</div>

<p>For every domain name in the list of referring domains to tag and track, a small table is created and underneath that each row displays stats for that day. 'Attempts to tag' displays the number of times a cookie was sent back to the browser. 'Preinstalled tags' shows that a cookie was found already installed on the browser.</p>

<h2>ReferringDomainTaggerModuleStats.aspx</h2>

<p>Open Notepad or Visual Studio and create an empty file with the name of 'ReferringDomainTaggerModuleStats.aspx' in any folder of your website.  Then copy and paste following code in it:</p>

<pre>
&lt;%@ Page Language=&quot;C#&quot; EnableSessionState=&quot;ReadOnly&quot; %&gt;

&lt;%@ Import Namespace=&quot;System.Collections.Generic&quot; %&gt;
&lt;%@ Import Namespace=&quot;Stardeveloper.Modules&quot; %&gt;

&lt;script runat=&quot;server&quot;&gt;
  void Page_Load(object source, EventArgs e)
  {
    if (IsPostBack)
      return;

    List&lt;ReferringDomain&gt; referringDomains = ReferringDomainTaggerModule.ReferringDomainsToTag;

    lock (referringDomains)
    {
      for (int i = 0; i &lt; referringDomains.Count; i++)
      {
        ReferringDomain d = referringDomains[i];

        HtmlTable table = new HtmlTable();
        table.Attributes[&quot;class&quot;] = &quot;domainStatsTable&quot;;
        form1.Controls.Add(table);

        // Creating the header row
        HtmlTableRow headerRow = new HtmlTableRow();
        table.Rows.Add(headerRow);

        HtmlTableCell headerCell = new HtmlTableCell();
        headerRow.Cells.Add(headerCell);

        headerCell.Attributes[&quot;class&quot;] = &quot;header&quot;;
        headerCell.ColSpan = 3;
        headerCell.Controls.Add(new LiteralControl(d.Domain));

        // Creating column headers
        HtmlTableRow colHeaderRow = new HtmlTableRow();
        table.Rows.Add(colHeaderRow);

        HtmlTableCell col1Cell = new HtmlTableCell();
        colHeaderRow.Cells.Add(col1Cell);

        HtmlTableCell col2Cell = new HtmlTableCell();
        colHeaderRow.Cells.Add(col2Cell);

        HtmlTableCell col3Cell = new HtmlTableCell();
        colHeaderRow.Cells.Add(col3Cell);

        col1Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
        col1Cell.Controls.Add(new LiteralControl(&quot;Date&quot;));

        col2Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
        col2Cell.Controls.Add(new LiteralControl(&quot;Attempts to tag&quot;));

        col3Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
        col3Cell.Controls.Add(new LiteralControl(&quot;Preinstalled tags&quot;));

        IList&lt;string&gt; keysInHitsList = d.HitsPerDayList.Keys;

        for (int j = 0; j &lt; keysInHitsList.Count; j++)
        {
          string key = keysInHitsList[j];
          ReferringDomainStats hd = d.HitsPerDayList[key];

          // Creating a row for each date
          HtmlTableRow row = new HtmlTableRow();
          table.Rows.Add(row);

          HtmlTableCell dateCell = new HtmlTableCell();
          row.Cells.Add(dateCell);

          HtmlTableCell attemptsCell = new HtmlTableCell();
          row.Cells.Add(attemptsCell);

          HtmlTableCell preinstalledCell = new HtmlTableCell();
          row.Cells.Add(preinstalledCell);

          dateCell.Controls.Add(new LiteralControl(key));
          attemptsCell.Controls.Add(new LiteralControl(Convert.ToString(hd.AttemptsToTag)));
          preinstalledCell.Controls.Add(new LiteralControl(Convert.ToString(hd.PreinstalledTags)));
        }
      }
    }
  }
&lt;/script&gt;

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
  &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Stats for ReferringDomainTaggerModule (&amp;copy;Stardeveloper.com)&lt;/title&gt;
    &lt;style type=&quot;text/css&quot;&gt;
      body { font-family: &quot;Trebuchet MS&quot;, &quot;Tahoma&quot;; font-size: 10pt;  margin: 0px; padding: 20px; }
      
    table { width: 440px; border-style: solid; border-width: 1px; }
    table + table { margin-top: 20px; }
    td { text-align: center; vertical-align: top;  border-style: solid; border-width: 1px; padding: 2px; }
    
    .header { font-weight: bolder; color: White; }
    
    .domainStatsTable { border-color: #98B1C4; }
    .domainStatsTable td { border-color: #98B1C4; }
    .domainStatsTable .header { background-color: #4C6E94; }
    .domainStatsTable .colHeader { background-color: #ACBFD0; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;p&gt;Learn more about &lt;a href=&quot;http://www.stardeveloper.com/articles/referring-domain-tagger-application/&quot;&gt;Referring Domain Tagger Application&lt;/a&gt;.&lt;br /&gt;
    Author: &lt;a href=&quot;http://blog.stardeveloper.com&quot;&gt;Faisal Khan&lt;/a&gt; (&lt;a href=&quot;http://www.stardeveloper.com&quot;&gt;Stardeveloper.com&lt;/a&gt;)&lt;/p&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>

<p>Once you have pasted the code and saved the page, you can either move to the next page to create the next component for this application or you can look at the explanation of the code given below to understand how this ASP.NET page works.</p>

<h2>Explanation</h2>

<p>The first thing we do is to tell the ASP.NET compiler that we will be using C# to write the code on this page.</p>

<p>Next, we tell ASP.NET runtime that no new session should be created for this page.</p>

<pre>
&lt;%@ Page Language=&quot;C#&quot; EnableSessionState=&quot;ReadOnly&quot; %&gt;</pre>

<p>We import couple of namespaces to make use of the generic collections and to access <code>ReferringDomainTaggerModule</code> HTTP module that we created earlier.</p>

<pre>
&lt;%@ Import Namespace=&quot;System.Collections.Generic&quot; %&gt;
&lt;%@ Import Namespace=&quot;Stardeveloper.Modules&quot; %&gt;</pre>

<p>Our code will be placed in the <code>Page_Load()</code> method.</p>

<pre>
&lt;script runat=&quot;server&quot;&gt;
	void Page_Load(object source, EventArgs e)
	{
		...
	}
&lt;/script&gt;</pre>

<p>The first thing we do within this method is to check if this is a post-back. A post-back occurs when an ASP.NET page is posted back to itself as a result of some action taken by the user. In post-back, the state of the controls is mostly maintained so that is why we don't touch our controls and exit out of this method if it is a post-back.</p>

<pre>
if (IsPostBack)
	return;</pre>

<p>Next, we save the reference to <code>ReferringDomainTaggerModule.ReferringDomainsToTag</code> in a local variable. <code>ReferringDomainTaggerModule.ReferringDomainsToTag</code> is a list of all referring domains we are tagging. It also provides access to domain stats as we'll see in a moment.</p>

<pre>
List&lt;ReferringDomain&gt; referringDomains = ReferringDomainTaggerModule.ReferringDomainsToTag;</pre>

<p>Since accessing a shared class-level object is a thread-unsafe procedure, we <code>lock</code> the object to prevent inadvertent read/write operation by two or more threads at the same time.</p>

<pre>
lock (referringDomains)
{
	...
}</pre>

<p>We then iterate through the list of referring domains. During each iteration, we create a new HTML table for that domain. Next, we iterate through the per-day records maintained of that domain and write an HTML row for each record found. Once all the tables have been created, we exit out of this method.</p>

<pre>
for (int i = 0; i &lt; referringDomains.Count; i++)
{
	ReferringDomain d = referringDomains[i];

	HtmlTable table = new HtmlTable();
	table.Attributes[&quot;class&quot;] = &quot;domainStatsTable&quot;;
	form1.Controls.Add(table);

	// Creating the header row
	HtmlTableRow headerRow = new HtmlTableRow();
	table.Rows.Add(headerRow);

	HtmlTableCell headerCell = new HtmlTableCell();
	headerRow.Cells.Add(headerCell);

	headerCell.Attributes[&quot;class&quot;] = &quot;header&quot;;
	headerCell.ColSpan = 3;
	headerCell.Controls.Add(new LiteralControl(d.Domain));

	// Creating column headers
	HtmlTableRow colHeaderRow = new HtmlTableRow();
	table.Rows.Add(colHeaderRow);

	HtmlTableCell col1Cell = new HtmlTableCell();
	colHeaderRow.Cells.Add(col1Cell);

	HtmlTableCell col2Cell = new HtmlTableCell();
	colHeaderRow.Cells.Add(col2Cell);

	HtmlTableCell col3Cell = new HtmlTableCell();
	colHeaderRow.Cells.Add(col3Cell);

	col1Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
	col1Cell.Controls.Add(new LiteralControl(&quot;Date&quot;));

	col2Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
	col2Cell.Controls.Add(new LiteralControl(&quot;Attempts to tag&quot;));

	col3Cell.Attributes[&quot;class&quot;] = &quot;colHeader&quot;;
	col3Cell.Controls.Add(new LiteralControl(&quot;Preinstalled tags&quot;));

	IList&lt;string&gt; keysInHitsList = d.HitsPerDayList.Keys;

	for (int j = 0; j &lt; keysInHitsList.Count; j++)
	{
		string key = keysInHitsList[j];
		ReferringDomainStats hd = d.HitsPerDayList[key];

		// Creating a row for each date
		HtmlTableRow row = new HtmlTableRow();
		table.Rows.Add(row);

		HtmlTableCell dateCell = new HtmlTableCell();
		row.Cells.Add(dateCell);

		HtmlTableCell attemptsCell = new HtmlTableCell();
		row.Cells.Add(attemptsCell);

		HtmlTableCell preinstalledCell = new HtmlTableCell();
		row.Cells.Add(preinstalledCell);

		dateCell.Controls.Add(new LiteralControl(key));
		attemptsCell.Controls.Add(new LiteralControl(Convert.ToString(hd.AttemptsToTag)));
		preinstalledCell.Controls.Add(new LiteralControl(Convert.ToString(hd.PreinstalledTags)));
	}
}</pre>

<p>The HTML table controls created above, are inserted in the <code>form1</code> control.</p>

<pre>
&lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
&lt;/form&gt;</pre>

<p>This in nutshell is pretty much what this ASP.NET page does.</p>

<p>Now that you have created this ASP.NET page, move over to the next page to create the custom web server control to display site-specific content to the tagged users of your website.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-module-stats-aspx/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 06 Dec 2010 08:22:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>An HTTP Module to tag users from given referring domains</title>
<link><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/]]></link>
<description><![CDATA[<p>This HTTP module will tag users, that is, place a cookie in the user's browser, if they visit our website by following a link from another website whose name we have added in the list of domain names to tag in our web.config file. Just like the list of domain names (or referring websites) can change, so can change the value of the cookie this module will place in the browser. The code that this module will have will be sufficient to handle all the changes, that is, to add and remove values in the cookie, or to remove the cookie all together.</p>

<p>If you are not up to speed with what ASP.NET application we are developing and how this application will tag and identify users, please read the <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/">introduction to tagging users using cookies</a> and get an <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-application/">overview of this application</a> to understand it in detail. We'll only focus on developing the HTTP module and code its logic from here onwards.</p>

<p>It is a self-sufficient module and doesn't need extra files or classes for its functionality. All it looks for are two key/value pairs in the <code>appSettings</code> section of web.config file. One pair to load the comma-separated list of domain names to tag and the second pair to add your UTC offset to the date and time to correctly log the stats for this application as per the date and time where you live. The moment you upload this module's file to the /App_Code folder of your ASP.NET website, and configure the two application level variables, this module will begin to work instantly and your users will begin to get tagged if they visit your website from the referring domains you have added in the web.config file. It is a silent module and works efficiently to handle every request with minimum of server resources.</p>

<p>Let us look at the code now.</p>

<h2>Stardeveloper.Modules.ReferringDomainTaggerModule.cs</h2>

<p>Please create a new file in Notepad or Visual Studio and save it as 'Stardeveloper.Modules.ReferringDomainTaggerModule.cs' in your /App_Code folder of your ASP.NET website. Now copy the following code and paste it into this file and hit the 'Save' button:</p>

<pre>
// Author: Faisal Khan (http://www.stardeveloper.com)

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;

namespace Stardeveloper.Modules
{
  public class ReferringDomainTaggerModule : IHttpModule
  {
    public const string CookieName_TaggedDomains = &quot;SD_TaggedDomains&quot;;

    public static List&lt;ReferringDomain&gt; ReferringDomainsToTag = new List&lt;ReferringDomain&gt;();
    public static int UtcOffset = 0;
    protected static bool Loaded = false;

    public ReferringDomainTaggerModule()
    {
      LoadReferringDomainsToTag();
    }

    public void Init(HttpApplication app)
    {
      app.BeginRequest += new EventHandler(app_BeginRequest);
    }

    protected void app_BeginRequest(object sender, EventArgs e)
    {
      HttpApplication app = sender as HttpApplication;
      HttpRequest req = app.Request;
      HttpResponse res = app.Response;
      Uri urlReferrer = req.UrlReferrer;

      if (Loaded)
      {
        // If there is no domain to tag, we will remove the cookie if found in the user's browser
        if (ReferringDomainsToTag.Count == 0)
        {
          HttpCookie refCk = req.Cookies[CookieName_TaggedDomains];

          if (refCk != null)
          {
            res.Cookies[CookieName_TaggedDomains].Value = String.Empty;
            res.Cookies[CookieName_TaggedDomains].Expires = DateTime.Now.AddYears(-1);

            return;
          }
        }
        else
        {
          // Check to see if user is coming to this website by clicking a link from another website
          if (urlReferrer != null)
          {
            ReferringDomain matchedReferringDomain = null;

            // Check to see if the referring domain is one of the domains in our list to tag
            for (int i = 0; i &lt; ReferringDomainsToTag.Count; i++)
            {
              ReferringDomain rd = ReferringDomainsToTag[i];

              if (urlReferrer.Host.IndexOf(rd.Domain, StringComparison.OrdinalIgnoreCase) != -1)
              {
                matchedReferringDomain = rd;
                break;
              }
            }

            // If we had a match
            if (matchedReferringDomain != null)
            {
              HttpCookie refCk = req.Cookies[CookieName_TaggedDomains];

              if (refCk == null)
              {
                // Create and place a new cookie
                refCk = new HttpCookie(CookieName_TaggedDomains, matchedReferringDomain.Domain);
                refCk.Expires = DateTime.Now.AddYears(10);

                res.Cookies.Add(refCk);

                matchedReferringDomain.IncrementAttemptsToTag();
              }
              else
              {
                string refCkVal = refCk.Value;

                if (refCkVal.IndexOf(matchedReferringDomain.Domain, StringComparison.OrdinalIgnoreCase) != -1)
                {
                  matchedReferringDomain.IncrementPreinstalledTags();
                }
                else
                {
                  refCkVal += &quot;,&quot; + matchedReferringDomain.Domain;

                  refCkVal = StripOldDomains(refCkVal);
                  matchedReferringDomain.IncrementAttemptsToTag();
                }

                res.Cookies[CookieName_TaggedDomains].Value = refCkVal;
                res.Cookies[CookieName_TaggedDomains].Expires = DateTime.Now.AddYears(10);
              }
            }
          }
        }
      }
    }

    public void Dispose()
    {
    }

    protected void LoadReferringDomainsToTag()
    {
      if (Loaded == false)
      {
        lock (ReferringDomainsToTag)
        {
          // Retrieving the list of domains to tag
          string retrievedList = ConfigurationManager.AppSettings[&quot;SD_ReferringDomainTaggerModule_ReferringDomainsToTag&quot;];

          if (!String.IsNullOrEmpty(retrievedList))
          {
            ReferringDomainsToTag.Clear();

            string[] retrievedListSplit = retrievedList.Split(',');

            for (int i = 0; i &lt; retrievedListSplit.Length; i++)
            {
              string referringDomain = retrievedListSplit[i].Trim();

              if (referringDomain != String.Empty)
                ReferringDomainsToTag.Add(new ReferringDomain(referringDomain));
            }

            // Retrieving UTC offset
            string utcOffsetStr = ConfigurationManager.AppSettings[&quot;SD_ReferringDomainTaggerModule_UtcOffset&quot;];

            if (!String.IsNullOrEmpty(utcOffsetStr))
              UtcOffset = Convert.ToInt32(utcOffsetStr);
          }

          Loaded = true;
        }
      }
    }

    protected string StripOldDomains(string refCkVal)
    {
      if (!String.IsNullOrEmpty(refCkVal))
      {
        StringBuilder newRefCkValBuilder = new StringBuilder();
        string[] refCkValSplit = refCkVal.Split(',');

        for (int i = 0; i &lt; refCkValSplit.Length; i++)
        {
          string refCkDomain = refCkValSplit[i];

          for (int j = 0; j &lt; ReferringDomainsToTag.Count; j++)
          {
            if (refCkDomain.Equals(ReferringDomainsToTag[j].Domain, StringComparison.OrdinalIgnoreCase))
            {
              if (newRefCkValBuilder.Length &gt; 0)
                newRefCkValBuilder.Append(&quot;,&quot;);

              newRefCkValBuilder.Append(refCkDomain);
              break;
            }
          }
        }

        return newRefCkValBuilder.ToString();
      }

      return refCkVal;
    }
  }

  public class ReferringDomain
  {
    public string Domain { get; protected set; }
    public SortedList&lt;string, ReferringDomainStats&gt; HitsPerDayList = new SortedList&lt;string, ReferringDomainStats&gt;();

    public ReferringDomain(string domain)
    {
      Domain = domain;
    }

    public string GetLocalCurrDateStr()
    {
      DateTime currLocalDateTime = DateTime.UtcNow.AddHours(ReferringDomainTaggerModule.UtcOffset);
      StringBuilder currDateStrBuilder = new StringBuilder(8);

      currDateStrBuilder.Append(currLocalDateTime.Month).Append(&quot;/&quot;);
      currDateStrBuilder.Append(currLocalDateTime.Day).Append(&quot;/&quot;);
      currDateStrBuilder.Append(currLocalDateTime.Year);

      return currDateStrBuilder.ToString();
    }

    public ReferringDomainStats GetHitsDetails()
    {
      string currLocalDateStr = GetLocalCurrDateStr();
      ReferringDomainStats hitsDetails = null;
      
      HitsPerDayList.TryGetValue(currLocalDateStr, out hitsDetails);

      if (hitsDetails == null)
      {
        // New day, new hits
        hitsDetails = new ReferringDomainStats();
        HitsPerDayList.Add(currLocalDateStr, hitsDetails);
      }

      return hitsDetails;
    }

    public void IncrementAttemptsToTag()
    {
      lock (HitsPerDayList)
      {
        GetHitsDetails().AttemptsToTag++;
      }
    }

    public void IncrementPreinstalledTags()
    {
      lock (HitsPerDayList)
      {
        GetHitsDetails().PreinstalledTags++;
      }
    }
  }

  public class ReferringDomainStats
  {
    public int AttemptsToTag { get; set; }
    public int PreinstalledTags { get; set; }
  }
}</pre>

<p>If by looking at the code you were able to figure out what it is doing or if you want to save time, then quickly move over to develop the next component for this application on the next page. Otherwise, a detailed explanation of the code follows.</p>

<h2>Explanation</h2>

<p>The very first line is a comment which gives credit to the developer of this application, <a href="http://blog.stardeveloper.com">Faisal Khan</a>, with a link to his website, <a href="http://www.stardeveloper.com">http://www.stardeveloper.com</a>.</p>

<pre>// Author: Faisal Khan (http://www.stardeveloper.com)</pre>

<p>Next, we are greeted with a long list of namespaces whose classes we are going to make use of in this HTTP module. Most of these namespaces are added automatically the moment we create a new C# file in Visual Studio.</p>

<p><code>System.Collections.Generic</code> is listed because we are going to make use of <code>List<></code> collection.</p>

<p><code>System.Configuration</code> is required because we want to access application level variables from web.config file and for that we need access to <code>ConfigurationManager</code> class that is present in this namespace.</p>

<p><code>System.Text</code> is for <code>StringBuilder</code> class and <code>System.Web</code> is for all the classes like <code>HttpRequest</code> and <code>HttpResponse</code> that we are going to use to read and write cookies to the user's browser.</p>

<p><code>System.Data</code> and <code>System.Data.SqlClient</code> are actually not needed since we are not going to access database in this application.</p>

<pre>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;</pre>

<p>Next, we declare a namespace, <code>Stardeveloper.Modules</code>, so that when we create <code>ReferringDomainTaggerModule</code> class, it does not conflict with another class of possibly the same name in your ASP.NET website. And also to put all the modules in one namespace, kind of grouping all the modules into their own namespace.</p>

<pre>
namespace Stardeveloper.Modules
{
}</pre>

<p>Next, we are create our <code>ReferringDomainTaggerModule</code> class and have it implement <code>IHttpModule</code> interface.</p>

<div class="note">For a class to work as an HTTP module in ASP.NET, it has to implement <code>IHttpModule</code> interface.</div>

<p>There are only two methods to implement in <code>IHttpModule</code> interface: <code>Init()</code> and <code>Dispose()</code>. By implementing this interface, our <code>ReferringDomainTaggerModule</code> class will be able to be deployed and run as an HTTP module on our ASP.NET website.</p>

<pre>
namespace Stardeveloper.Modules
{
  public class ReferringDomainTaggerModule : IHttpModule
  {
    public void Init(HttpApplication app)
    {
    }

    public void Dispose()
    {
    }
  }
}</pre>

<p>Within <code>ReferringDomainTaggerModule</code>, we declare <code>static</code> variables to provide global access to certain constant and variable elements of this class.</p>

<p><code>CookieName_TaggedDomains</code> is a constant to hold the <i>name</i> of the cookie we are going to read and write to the user's browser to save list of domain names he has been tagged with. By default, its name is <code>&quot;SD_TaggedDomains&quot;</code>.</p>

<pre>
public const string CookieName_TaggedDomains = &quot;SD_TaggedDomains&quot;;

public static List&lt;ReferringDomain&gt; ReferringDomainsToTag = new List&lt;ReferringDomain&gt;();
public static int UtcOffset = 0;
protected static bool Loaded = false;</pre>

<p>Next, we create the constructor for this class. In the constructor we are going to call a method which will load certain values from web.config into the class-level objects we have created above.</p>

<pre>
public ReferringDomainTaggerModule()
{
  LoadReferringDomainsToTag();
}</pre>

<p>When the HTTP module is created and is ready to serve requests, and one instance is created for each HTTP request that IIS receives, its <code>Init()</code> method is called to give an opportunity to the module to <i>register</i> for events in the HTTP request handling pipline.</p>

<div class="tip">This article provides good <a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=1">introduction to HTTP modules and HTTP request handling pipeline</a> in ASP.NET.</div>

<p>In the <code>Init()</code> method, we register to handle the <code>BeginRequest</code> event. This event is raised at the beginning of the HTTP request handling pipeline. This is the first event to be raised when an HTTP request is received by IIS. We will put the logic to scan the referring link and to read and write the cookie in this event handler, as we'll see in a moment.</p>

<pre>
public void Init(HttpApplication app)
{
  app.BeginRequest += new EventHandler(app_BeginRequest);
}</pre>

<p>Next, comes our event handler method which will be called when the <code>BeginRequest</code> event is raised at the start of the HTTP request handling pipeline.</p>

<pre>
protected void app_BeginRequest(object sender, EventArgs e)
{
}</pre>

<p>The first thing we do within this method is to store references to important objects, which we'll be using later, in local variables.</p>

<p>The caller (or sender as it is called in .NET) of this event (<code>BeginRequest</code>) is <code>HttpApplication</code> object. We obtain a reference to this object by casting the <code>sender</code> object to <code>HttpApplication</code> using the <code>as</code> keyword and saving this reference in the local variable, <code>app</code>.</p>

<p>We use the reference to <code>HttpApplication</code> to obtain references to <code>HttpRequest</code> and <code>HttpResponse</code> objects, and save them in local variables. These objects encapsulate HTTP request and response, respectively. Using the <code>HttpRequest</code> object, we obtain the reference to the referring <code>Uri</code> (or URL as it is more commonly called) object.</p>

<div class="note">The <code>HttpRequest.UrlReferrer</code> will return a <code>null</code> reference if this HTTP request did not have any referring link, that is, the user was not referred to this web page by following a link from another.</div>

<pre>
HttpApplication app = sender as HttpApplication;
HttpRequest req = app.Request;
HttpResponse res = app.Response;
Uri urlReferrer = req.UrlReferrer;</pre>

<p>Next, we check the <code>Loaded</code> variable to see if the list of domains to tag has been successfully loaded into an in-memory list. If so, then we check to see if this list is empty, that is, there are no domains to tag, then we remove the <code>&quot;SD_TaggedDomains&quot;</code> cookie if there is one in the user's browser.</p>

<p>We remove the cookie by setting its <code>Value</code> to an empty string and then setting its <code>Expires</code> property to a date in the past. When the browser will see that there is a cookie in the HTTP response whose expiry date has already passed, that is, the cookie has expired, the browser will remove the cookie from its store.</p>

<pre>
if (Loaded)
{
  // If there is no domain to tag, we will remove the cookie if found in the user's browser
  if (ReferringDomainsToTag.Count == 0)
  {
    HttpCookie refCk = req.Cookies[CookieName_TaggedDomains];

    if (refCk != null)
    {
      res.Cookies[CookieName_TaggedDomains].Value = String.Empty;
      res.Cookies[CookieName_TaggedDomains].Expires = DateTime.Now.AddYears(-1);

      return;
    }
  }
  else
  {
	...
  }
}</pre>

<p>Next, we check the referred <code>Uri</code> object to see if it is <code>null</code> or not by using the <code>urlReferrer</code> reference that we had saved earlier. If the user requested your page directly then this object reference will be <code>null</code>. If it is not null, that is, the user is coming from a link on another web page, then we proceed further.</p>

<p>We then iterate through the list of domain names that we have saved in the <code>List&lt;ReferringDomain&gt;</code> object referenced by <code>ReferringDomainTaggerModule.ReferringDomainsToTag</code> variable. Each <code>ReferringDomain</code> object refers to one domain name that we have included in the web.config file to tag. As we'll see just a while later, <code>ReferringDomain</code> class provides a property with the name of <code>Domain</code> that contains the domain name to tag. During the iteration through the list of domains to tag, we compare the domain name with the referring link's domain name. If there is match, that is, the user is coming from a domain name we'll like to tag, we proceed further.</p>

<pre>
// Check to see if user is coming to this website by clicking a link from another website
if (urlReferrer != null)
{
  ReferringDomain matchedReferringDomain = null;

  // Check to see if the referring domain is one of the domains in our list to tag
  for (int i = 0; i &lt; ReferringDomainsToTag.Count; i++)
  {
    ReferringDomain rd = ReferringDomainsToTag[i];

    if (urlReferrer.Host.IndexOf(rd.Domain, StringComparison.OrdinalIgnoreCase) != -1)
    {
      matchedReferringDomain = rd;
      break;
    }
  }

  // If we had a match
  if (matchedReferringDomain != null)
  {
    ...
  }
}</pre>

<p>Alright, we had a match. We have a user who is coming to our website from a website whose domain name we had put in the web.config file to tag. Now we have to <i>tag</i> this user. We'll do that my placing a cookie on this user's browser. We check the cookies (if any) sent by this browser to our website to see if there is already a cookie with the name of <code>&quot;SD_TaggedDomains&quot;</code> in that list. If there is not, then we create a new cookie with the name of <code>&quot;SD_TaggedDomains&quot;</code>. We set it's <code>Value</code> to the domain this user is to be tagged to, that is, the domain he was referred from, to our website. We set this cookie's expiry date far in the future by setting its <code>Expires</code> property to a date 10 years in the future. When this cookie is ready to be sent to the user's browser, we add it to the outgoing HTTP response stream.</p>

<p>To display some stats to the admin, that is, you, we call the <code>IncrementAttemptsToTag()</code> method of the matched <code>ReferringDomain</code> object. This method will internally increment the number of attempts that were made to send the cookie to the user's browser once there was a confirmed match. This internal log will be read by the <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-module-stats-aspx/">ReferringDomainTaggerModuleStats.aspx</a> page to display these stats in the form of a table. Later on that.</p>

<pre>
HttpCookie refCk = req.Cookies[CookieName_TaggedDomains];

if (refCk == null)
{
  // Create and place a new cookie
  refCk = new HttpCookie(CookieName_TaggedDomains, matchedReferringDomain.Domain);
  refCk.Expires = DateTime.Now.AddYears(10);

  res.Cookies.Add(refCk);

  matchedReferringDomain.IncrementAttemptsToTag();
}
else
{
  ...
}</pre>

<p>If the user already had the cookie, <code>&quot;SD_TaggedDomains&quot;</code>, then we check to see if this user is already tagged for this referring domain, that is, the user previously visited our website from this domain name and was tagged (a cookie was placed). If the user is already tagged, we log it by calling the <code>IncrementPreinstalledTags()</code> method of the <code>ReferringDomain</code> that was matched.</p>

<p>If the user had the cookie but was not tagged for this referring domain, we append the value of this domain name to the cookie's <code>Value</code>. We call <code>StripOldDomains()</code> method of this HTTP module to remove any stale domain names that are still residing in this cookie. You'll see the code for this method in a moment.</p>

<p>Finally, we update the cookie and set its <code>Expires</code> property to a date well advance in the future. And we are done processing.</p>

<pre>
string refCkVal = refCk.Value;

if (refCkVal.IndexOf(matchedReferringDomain.Domain, StringComparison.OrdinalIgnoreCase) != -1)
{
  matchedReferringDomain.IncrementPreinstalledTags();
}
else
{
  refCkVal += &quot;,&quot; + matchedReferringDomain.Domain;

  refCkVal = StripOldDomains(refCkVal);
  matchedReferringDomain.IncrementAttemptsToTag();
}

  res.Cookies[CookieName_TaggedDomains].Value = refCkVal;
  res.Cookies[CookieName_TaggedDomains].Expires = DateTime.Now.AddYears(10);</pre>

<p>There is nothing that we would want to do when this instance of <code>ReferringDomainTaggerModule</code> HTTP module is about to be disposed. So, we leave the body of this method, empty.</p>

<pre>
public void Dispose()
{
}</pre>

<p>Now, we'll code the body of the <code>LoadReferringDomainsToTag()</code> method. This method is called from within the constructor of <code>ReferringDomainTaggerModule</code> class. The purpose of this method is to:</p>

<ol>
<li>Retrieve the list of domain names to tag from web.config file and to add these domain names in the <code>ReferringDomainTaggerModule.ReferringDomainsToTag</code> list.</li>
<li>Retrieve UTC offset from  web.config file and save it in the <code>ReferringDomainTaggerModule.UtcOffset</code> variable.</li>
</ol>

<p>The first thing we do when we enter in this method is to check the <code>Loaded</code> variable to see if we have done the loading of domain names and UtcOffset already or not. If not, then we proceed further.</p>

<p>We <code>lock</code> the <code>ReferringDomainsToTag</code> <i>class</i> to prevent two threads simultaneously updating the shared variables.</p>

<p>The comma-separated list of domain names (for example, &quot;facebook.com,twitter.com,dzone.com&quot;) is retrieved from the web.config file. It is split and each domain name is placed in a <code>ReferringDomain</code> object. Each <code>ReferringDomain</code> object is then added to the <code>ReferringDomainTaggerModule.ReferringDomainsToTag</code> list.</p>

<p>The UtcOffset is retrieved and converted into an integer. It is then saved in the <code>ReferringDomainTaggerModule.UtcOffset</code> variable.</p>

<p>Lastly, we set the <code>Loaded</code> variable to <code>true</code> to prevent any repeat retrieval and addition of domain names and UtcOffset from the web.config file until the application is restarted, and release the lock to <code>ReferringDomainTaggerModule</code> class.</p>

<pre>
protected void LoadReferringDomainsToTag()
{
  if (Loaded == false)
  {
    lock (ReferringDomainsToTag)
    {
      // Retrieving the list of domains to tag
      string retrievedList = ConfigurationManager.AppSettings[&quot;SD_ReferringDomainTaggerModule_ReferringDomainsToTag&quot;];

      if (!String.IsNullOrEmpty(retrievedList))
      {
        ReferringDomainsToTag.Clear();

        string[] retrievedListSplit = retrievedList.Split(',');

        for (int i = 0; i &lt; retrievedListSplit.Length; i++)
        {
          string referringDomain = retrievedListSplit[i].Trim();

          if (referringDomain != String.Empty)
            ReferringDomainsToTag.Add(new ReferringDomain(referringDomain));
        }

        // Retrieving UTC offset
        string utcOffsetStr = ConfigurationManager.AppSettings[&quot;SD_ReferringDomainTaggerModule_UtcOffset&quot;];

        if (!String.IsNullOrEmpty(utcOffsetStr))
          UtcOffset = Convert.ToInt32(utcOffsetStr);
      }

      Loaded = true;
    }
  }
}</pre>

<p><code>StripOldDomains()</code> is a handy method to remove any domain names that have been removed from the list in web.config file but are still present in the cookie.</p>

<p>We split the list of domain names in the cookie's <code>Value</code> and match each of them with list of domain names to match to, present in our web.config file. If there is a match we append that domain name in our local <code>StringBuilder</code> object. This <code>StringBuilder</code> object represents the new list of domain names that this cookie is allowed to have.</p>

<p>If there is no match, then this means that the domain name in the cookie is old, then we don't append it in the <code>StringBuilder</code> object. Once the iteration through the list is complete, we return the <i>new</i> list of domain names for this cookie.</p>

<pre>
protected string StripOldDomains(string refCkVal)
{
  if (!String.IsNullOrEmpty(refCkVal))
  {
    StringBuilder newRefCkValBuilder = new StringBuilder();
    string[] refCkValSplit = refCkVal.Split(',');

    for (int i = 0; i &lt; refCkValSplit.Length; i++)
    {
      string refCkDomain = refCkValSplit[i];

      for (int j = 0; j &lt; ReferringDomainsToTag.Count; j++)
      {
        if (refCkDomain.Equals(ReferringDomainsToTag[j].Domain, StringComparison.OrdinalIgnoreCase))
        {
          if (newRefCkValBuilder.Length &gt; 0)
            newRefCkValBuilder.Append(&quot;,&quot;);

          newRefCkValBuilder.Append(refCkDomain);
          break;
        }
      }
    }

    return newRefCkValBuilder.ToString();
  }

  return refCkVal;
}</pre>

<p>Each domain name that you place in the list of domain names to tag in the web.config file, is at the time of loading placed in a separate instance of <code>ReferringDomain</code> class. This class not only represents a referring domain, but it contains an internal sorted list of dates (per day) and hits (attempts made at setting a cookie in the browser and if the cookie was found preinstalled in the user's browser).</p>

<pre>
public class ReferringDomain
{
  public string Domain { get; protected set; }
  public SortedList&lt;string, ReferringDomainStats&gt; HitsPerDayList = new SortedList&lt;string, ReferringDomainStats&gt;();

  public ReferringDomain(string domain)
  {
    Domain = domain;
  }

  public string GetLocalCurrDateStr()
  {
    DateTime currLocalDateTime = DateTime.UtcNow.AddHours(ReferringDomainTaggerModule.UtcOffset);
    StringBuilder currDateStrBuilder = new StringBuilder(8);

    currDateStrBuilder.Append(currLocalDateTime.Month).Append(&quot;/&quot;);
    currDateStrBuilder.Append(currLocalDateTime.Day).Append(&quot;/&quot;);
    currDateStrBuilder.Append(currLocalDateTime.Year);

    return currDateStrBuilder.ToString();
  }

  public ReferringDomainStats GetHitsDetails()
  {
    string currLocalDateStr = GetLocalCurrDateStr();
    ReferringDomainStats hitsDetails = null;
      
    HitsPerDayList.TryGetValue(currLocalDateStr, out hitsDetails);

    if (hitsDetails == null)
    {
      // New day, new hits
      hitsDetails = new ReferringDomainStats();
      HitsPerDayList.Add(currLocalDateStr, hitsDetails);
    }

    return hitsDetails;
  }

  public void IncrementAttemptsToTag()
  {
    lock (HitsPerDayList)
    {
      GetHitsDetails().AttemptsToTag++;
    }
  }

  public void IncrementPreinstalledTags()
  {
    lock (HitsPerDayList)
    {
      GetHitsDetails().PreinstalledTags++;
    }
  }
}</pre>

<p>The hits are saved by <code>ReferringDomain</code> in an internal list of <code>ReferringDomainStats</code> objects.</p>

<pre>
public class ReferringDomainStats
{
  public int AttemptsToTag { get; set; }
  public int PreinstalledTags { get; set; }
}</pre>

<h2>Where to place this file?</h2>

<p>As explained before, you have to save Stardeveloper.Modules.ReferringDomainTaggerModule.cs file in the /App_Code folder of your ASP.NET website.</p>

<p>The job is not complete and this module will not start to tag users until you add it in your web.config file and add two application level variables as well. We'll look that in next few pages.</p>

<p>Next, we'll move on to the next component of this Referring Domain Tagger Application which happens to be the <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-module-stats-aspx/">ReferringDomainTaggerModuleStats.aspx</a> ASP.NET page.</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 06 Dec 2010 08:17:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
<item>
<title>ASP.NET application to tag and identify users from Facebook, Twitter, Dzone and more</title>
<link><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-application/]]></link>
<description><![CDATA[<p>Users visit a website either directly by typing its address in the URL bar of the browser or when they visit a link to that website from another website or search engine. It is possible to <i>tag</i> a user visiting your website following a link on another popular website like Facebook or Twitter, by placing a small cookie on his browser. That cookie can be used to identify that user when he browses your website or visits it later. You can use the tag on this user's browser to display site specific content like displaying the 'Like' button to Facebook users and 'Retweet' button to Twitter users. You can <a href="http://www.stardeveloper.com/articles/display-dzone-voting-button-on-your-website-only-to-visitors-from-dzone/">display Dzone's voting button to its users</a>, not just for the link they visited to but for other articles and content on your website which they'll vote up if they like. Dzone users can even <i>submit</i> a link on your website to their network if they find it interesting and if it is not already there. Dzone's voting button will make it easier for them to do that. This application can prove quite helpful if you want to increase the appeal and traffic of your website across social networks and popular websites.</p>

<p>If you have not followed us from the start, we are developing an ASP.NET web application to tag users from certain websites and to display them relevant content by using custom web server controls. This is a slick and neatly developed application and the time you spend learning how it works, how to setup, and how to run the application on <i>your website</i> can reward you big time in the long run. You may want to read the introduction to learn <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/#why">why there is a need for this application</a>, <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/#how">how it works</a>, <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/#how-to">how to add and remove referring domains to be tagged</a>, <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/#remove">how to remove the tags if you'd want</a>, and <a href="http://www.stardeveloper.com/articles/what-is-user-referring-domain-tagging/#requirements">what is needed to run this application</a>.</p>

<h2>Live demonstration of a working example of this application</h2>

<p>While you will come to see a <a href="http://www.stardeveloper.com/articles/display-dzone-voting-button-on-your-website-only-to-visitors-from-dzone/">live demonstration of this application</a> working on Stardeveloper.com, later, I am going to show a couple of images from an article on this website. In the following images you can see that a Dzone voting button gets shown only to a user who visited this website from Dzone.com:</p>

<div class="image">
	<a href="http://www.stardeveloper.com/images/displaying-article-to-an-untagged-user.png"><img src="http://www.stardeveloper.com/images/displaying-article-to-an-untagged-user-thumbnail.png" width="300" height="190" border="0" alt="No Dzone voting button for other users of Stardeveloper.com" /></a>
	<div class="imagedesc">No Dzone voting button for other users of Stardeveloper.com<br />
	(click the image to view in full size)</div>
</div>

<div class="image">
	<a href="http://www.stardeveloper.com/images/displaying-dzone-badge-only-to-a-dzone-tagged-user.png"><img src="http://www.stardeveloper.com/images/displaying-dzone-badge-only-to-a-dzone-tagged-user-thumbnail.png" width="300" height="190" border="0" alt="No Dzone voting button for other users of Stardeveloper.com" /></a>
	<div class="imagedesc">Dzone voting button being shown to a visitor from Dzone.com<br />
	(click the image to view in full size)</div>
</div>

<p>We'll now take a look at a short introduction to understand the design and structure of this application which we'll call 'Referring Domain Tagger Application' from here onwards.</p>

<h2>Introduction to Referring Domain Tagger Application</h2>

<p>It is a small plug and play ASP.NET web application. Apart from minor updates to your web.config file, there are no changes required to be made to your existing ASP.NET website. So you should be able to plug this application in, without much hassle. Following is the list of components this application is made of:</p>

<ol style="list-style-type: decimal">
<li><b><code>ReferringDomainTaggerModule</code></b>
	<p>This is a small <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">HTTP module</a> whose function is to scan the referring links and to match their domain names with the list of domain names we have provided in the web.config file. If their is a match then this module will place a cookie, <code>&quot;SD_TaggedDomains&quot;</code>, as a tag in the user's browser. This cookie will be used later by the custom web server control to identify the tag and display specific content for that, like displaying the 'Like' button for Facebook users as we have talked previously.</p></li>
<li><b>ReferringDomainTaggerModuleStats.aspx</b>
	<p>It is an ASP.NET page that will display stats for the cookies placed (or attempts made to place the cookie since we don't know if the browser is accepting cookies or not). The HTTP module above will log stats for each domain we are attempting to tag, in its memory. This ASP.NET page will scan that log and display the stats to you, the admin. Remember: the stats are refreshed each time the ASP.NET application is restarted because the log is maintained in memory and not in the database.</p>
	
	<p>Following image shows sample stats as they will be displayed by this ASP.NET page:</p>

	<div class="image">
		<a href="http://www.stardeveloper.com/images/referring-domain-tagger-module-stats-aspx.png">
		<img src="http://www.stardeveloper.com/images/referring-domain-tagger-module-stats-aspx-thumbnail.png" width="300" height="163" alt="Sample stats from ReferringDomainTaggerModuleStats.aspx" border="0" /></a>
		<div class="imagedesc">Sample stats from ReferringDomainTaggerModuleStats.aspx<br />
		(click the image to view in full size)</div>
	</div></li>
<li><b><code>TaggedDomainMatcherControl</code></b>
	<p>It is a custom web server control that we will develop later. The only custom attribute this control will have is <code>DomainToMatch</code> which takes, as its name implies, the domain name to match. If the user is already tagged with that domain name by the HTTP module, that is, was referred from that domain, the user will be displayed the content <i>enclosed</i> by this control.</p>
	<pre>
&lt;sd:TaggedDomainMatcherControl DomainToMatch=&quot;dzone.com&quot; runat=&quot;server&quot;&gt;
	&lt;p&gt;Hi Dzone user!&lt;/p&gt;
&lt;/sd:TaggedDomainMatcherControl&gt;</pre>
	<p>Above code shows what it will take to make use of <code>TaggedDomainMatcherControl</code> and how to specify a domain name in the <code>DomainToMatch</code> attribute. The message, &quot;Hi Dzone user!&quot;, will only be shown to users who were referred from Dzone.com or who have in their cookie, <code>&quot;SD_TaggedDomains&quot;</code>, the domain name &quot;dzone.com&quot;.</p>
</li>
<li><b>Web.config</b>
	<p>The last component, or shall I say step, is making a few changes in web.config file. There are just two key/value pairs to be added in the application settings. After that, we'll configure the above HTTP module and we are all done.</p></li>
</ol>

<h2>How this application works?</h2>

<p>The absolutely key component of this application is the <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">ReferringDomainTaggerModule</a> which is an HTTP module that does all the work of reading and writing cookies in the user's browser, that is, <i>tagging</i> him with the domain that referred him to our website. If you only install this HTTP module, the users will begin to get tagged. That's it. No other component or file is needed to tag or untag the users.</p>

<p>Practically speaking though, you'll want to make some use of those tags, right? This is where the second most important component of this application comes in, and this is <a href="http://www.stardeveloper.com/articles/tagged-domain-matcher-control/">TaggedDomainMatcherControl</a>. It is a custom web server control that makes it easy to add site or domain specific content in your ASP.NET pages with just a couple of lines of code, as we saw above. If you have this control in your website, using this application becomes a breeze. No other component is required to run or make use of this application.</p>

<p>The <a href="http://www.stardeveloper.com/articles/referring-domain-tagger-module-stats-aspx/">ASP.NET page to display stats</a> is purely optional. It only displays what the HTTP module logs in its memory. You will like to have this ASP.NET page some where protected in your admin only folder. This ASP.NET page will display (not change any settings) the stats of each domain on a per day basis. Whenever you restart your ASP.NET application or update your web.config file, the changes will be lost and the stats will start to get recorded from zero. You'll be fine if you just want to delete this file all together, it is entirely up to you.</p>

<p>There is no other file to create, code to develop or to changes to make in your existing ASP.NET pages. An application level variable to tell the HTTP module which referring domains to tag and another one to configure UTC offset to correctly log dates per <i>your</i> UTC offset and not your web server's, is what you'll have to add to your web.config file. Then configure HTTP module and you are all done. It is that simple!</p>

<h2>Start developing!</h2>

<p>Now that we know what tagging is all about, what our application consists of and how it all works, let us open our editors and code the first component, that is, 
	<a href="http://www.stardeveloper.com/articles/referring-domain-tagger-http-module/">Stardeveloper.Modules.ReferringDomainTaggerModule.cs</a> file for our HTTP module. Move to the next page please!</p>]]></description>
<guid isPermaLink="true"><![CDATA[http://www.stardeveloper.com/articles/referring-domain-tagger-application/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 06 Dec 2010 08:13:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /></item>
</channel>
</rss>
