back to Jitbit Blog home About this blog

SEO friendly URLs with ASP.NET

by Alex Yumashev · Dec 15 2007
Search engines like human-readable URLs with keywords in it, and hesitate to respect messy URLs with a lot of query-string parameters. So, to make our ASP.NET database-driven website SEO-friendly we have to get rid of our complex URLs.

Example of a "SEO-friendly" URL:
http://www.jitbit.com/helpdesk.aspx

Example of a "SEO-unfriendly" URL:
http://www.jitbit.com/product.aspx?ProductID=13

Solution 1: Fake pages and "Server.Transfer". As you can see the two URLs above point to the same page. Basically it is the same page and it works like this: the page helpdesk.aspx contains no code at all and performs a Server.Transfer (aka server-side redirect) to product.aspx like this:

Server.Transfer("product.aspx?ProductID=13");

That's it. We have one "product.aspx" page which expects a "ProductID" parameter and a lot of "fake pages" with SEO-friendly names like firstproduct.aspx, secondproduct.aspx etc., which simply perform a Server.Transfer to the "product.aspx" with the right ProductID.

Simple, isn't it?

But this solution requires a lot of hard-coding - we will have to create all these fake pages and add a Server.Transfer command. So let's go a little further: we will create one base class for all our "fake pages" and add a record to the "tblProducts" table in the database:

tblProducts
ProductIDProductNameProductPage
1First Productfirstproduct.aspx
2Second Productsecondproduct.aspx
3Third Productthirdproduct.aspx


public class ProductPage : Page
{
private SqlConnection cn;
private SqlCommand cmd;
protected override void OnLoad(EventArgs e)
{
//lets initialize our database connection
//remember to specify the connection string
cn = new SqlConnection(yourConnectionString);
cmd = new SqlCommand();
cmd.Connection = cn;

//determine the page being requested in the browser
string pageFileName = Request.Path.Substring(Request.Path.LastIndexOf("/")+1);

//get the right ProductID from the database
cmd.CommandText = "SELECT ProductID FROM tblProducts WHERE ProductPage=@ProductPage";
cmd.Parameters.AddWithValue("@ProductPage", pageFileName);
cn.Open();
object productID = cmd.ExecuteScalar();
cn.Close();

//if ProductID found
if(productID!=null && productID!=DBNull.Value)
{
//let's transfer the execution
Server.Transfer("product.aspx?ProductID=" + productID.ToString());
}
}
}
Now we have to create our fake pages, inherit them all from the ProductPage class and voi la - that's it! We can also optionally remove all the HTML-code from the aspx-files, leaving the "Page" directive only.

Solution 2: Virtual Pages. This method is pretty similar, except that we don't need to create any pages at all. Instead, we will add an HttpModule, which intercepts HTTP requests, and the user requests a non-existent page, performs a Rewrite operation. First we will create our HttpModule:


namespace URLRewrite
{
public class ProductPageModule : IHttpModule
{
public ProductPageModule()
{
}

public void Dispose()
{
}

public void Init(HttpApplication application)
{
//let's register our event handler
application.PostResolveRequestCache += (new EventHandler(this.Application_OnAfterProcess));
}

private void Application_OnAfterProcess(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;

//the file being requested is not found
if (!File.Exists(application.Request.PhysicalPath))
{
//replace the "newURL"
//with your own value
string newURL = "product.aspx?ProductID=13";
context.RewritePath(newURL);
}
}
}
}
Now we have to register our HttpModule in the web.config:

<httpModules>
<add type="URLRewrite.ProductPageModule, URLRewrite" name="ProductPageModule" />
<httpModules>

That's it.