URL Rewriting with IIS 7 and .NET 4.0

By March 14, 2013 asp.net, code, SEO

I have been focusing more and more on Search Engine Optimization for my clients and recently needed to modify a site to create better search friendly URLs by removing the default document from the URL, forcing all requests to the domain without the WWW and converting some querystring parameters to be search engine friendly.  In the past, especially when using a managed hosting account such as godaddy or the like, you might not have had the level of access you needed to install components that would allow you to rewrite URLs.  Now with the IIS URL Rewrite 2.0 module, .NET 4, and IIS 7+, things have gotten much easier.

Here is an example of modifications you can make to the web.config file and the global.asax file to do the following:

  • Redirect all requests from www.mysite.com to mysite.com
  • Remove the default.aspx extension from the URL so that mysite.com/folder/default.aspx becomes mysite.com/folder
  • Remove the .aspx extension from the URL so mysite.com/mypage.aspx becomes mysite.com/mypage

 

The Web.config file:

<?xml version="1.0"?>
<configuration> 
	<system.web>
		<compilation debug="false" targetFramework="4.0"/>   
	</system.web>
	<system.webServer>    
		<rewrite>
			
			<rules>
				<rule name="Redirect aspx to extensionless" stopProcessing="true">
				<match url="(.*)\.aspx" />
				<action type="Redirect" url="{R:1}" redirectType="Permanent" />
			</rule>        

			<rule name="Canonical Host Name Remove WWW" stopProcessing="true">
				<match url="^(.*)$" />
				<conditions>
					<add input="{HTTP_HOST}" pattern="^(www\.)(.*)$" />
				</conditions>
				<action type="Redirect" url="http://yourdomainname.com{PATH_INFO}" redirectType="Permanent" />
			</rule>        

			<rule name="Default Document" stopProcessing="true">
				<match url="(.*)default.aspx" />
				<action type="Redirect" url="{R:1}" redirectType="Permanent" />
			</rule>

			<rule name="rewrite the aspx extension">
				<match url="(.*)" />
				<conditions logicalGrouping="MatchAll">
					<add input="{URL}" negate="true" pattern="\.axd$" />
					<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
					<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
				</conditions>
				<action type="Rewrite" url="{R:1}.aspx" redirectType="Permanent"/>
			</rule>

		</rules>
		</rewrite>
	</system.webServer>
</configuration>

Note: If you have a directory where you do NOT want all the rewriting to take place, put the following in a web.config file in that directory.

<rewrite>
     <rules>
          <clear />
     </rules>
</rewrite>

 

The following changes in the global.asax file allow you to convert a URL from mysite.com/folder/mypage.aspx?client=4 to mysite.com/folder/my-client-name.  It is accomplished using the URL Routing engine.

The two areas to be concerned with in the global.asax file:

<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Routing" %>

void Application_Start(object sender, EventArgs e) 
{        
    RegisterRoutes(System.Web.Routing.RouteTable.Routes);
}

void RegisterRoutes(System.Web.Routing.RouteCollection routes)
{
     routes.MapPageRoute("routename", "folder/{clientname}", "~/folder/mypage.aspx");
}

 

Once the above is in place in the global.asax file, you can then work with the route in your code behind by using a database query to dynamically replace values or manually adjusting them as needed.

For example if you have a asp:repeater on the page and want to populate the repeater with rewritten hyperlinks, something like the following might be of use:

protected void rp_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
        {
            DataRowView drv = (DataRowView)e.Item.DataItem;

            RouteValueDictionary paramters = new RouteValueDictionary{ 
                                            {"routename", drv["clientname"].ToString()) }
                                                            };

            VirtualPathData vpd = RouteTable.Routes.GetVirtualPath(null, "routename", paramters);

            HyperLink hyp = (HyperLink)e.Item.FindControl("hyp");
            hyp.NavigateUrl = vpd.VirtualPath;
            hyp.Text = drv["clientname"].ToString();
            hyp.Font.Bold = true;
            
        }
    }

 

Depending on how your data is setup, you want to be sure to replace any spaces or special characters to the URL is friendly. mysite.com/client-name-here is better than mysite.com/client%20name%20here.

Here are some helpful links that continue to help my along my way:

 

And once you are done, you might need some of this stuff.