I'm sure there are many blog articles out there, but I'd figure I'd add another post. Mostly fo rmyself to refer to, but also for anyone else stumbling on the issue. In the code I'm about to post there are some objects that are used in the main method of which the code I won't display... however, you can pretty much tell what I'm sort of doing within the code to "Matlock" it out.
Once I figured out how easy it was to do without a 3rd party add-on and how it was mentioned that with thousands of products the regex matching would be slower and that it was recommended that I create may have to create my own provider plug-in for the third party tools (which is unnecessary and adding to the complexity) I decided it would be easiest and fastest to "roll my own." It's rather simple and it uses regex as well, but only a single match is required per request... Here is my sample code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text.RegularExpressions;
namespace Producs.Rewrite
{
/// <summary>
/// URL ReWrite Rules for the Products
/// </summary>
public class ProductRewrite : IHttpModule
{
HttpContext context;
public ProductRewrite()
{
}
#region IHttpModule Members
public void Dispose()
{
//nothing to dispose
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler
(context_BeginRequest);
}
#endregion
private void context_BeginRequest(object sender, EventArgs e)
{
context = HttpContext.Current;
Regex regex = new Regex("^(.*)/Products/(.*)\\.aspx$",
RegexOptions.IgnoreCase);
Regex productPageRule = new Regex("^(.*)/Products/
product.aspx(\\?)?(d=(.*))?$", RegexOptions.IgnoreCase);
Regex ProductsListPage = new Regex("^(.*)/Products/
Products.aspx(\\?(.*))?");
string url = context.Request.RawUrl +
(context.Request.QueryString == null ? "" :
context.Request.QueryString.ToString());
if(productPageRule.IsMatch(url))
return; // do nothing if the request is a direct
request to the product.aspx?d= page.
if (regex.IsMatch(url) && (!ProductsListPage.IsMatch
(url)))
{
try
{
if (HttpContext.Current.Cache["ListOfAllProducts"]
== null)
{
HttpContext.Current.Cache.Insert
("ListOfAllProducts", Common.LoadProducts(), null
, DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration);
}
Akdproduct product = ((List<Akdproduct>)
HttpContext.Current.Cache["ListOfAllProducts"])
.Find(d => d.Slug == GetPageName
(context.Request.RawUrl).Replace(".aspx", ""));
url = url.Replace(product.Slug + ".aspx",
"product.aspx?d=" + product.ID);
context.RewritePath(url);
}
catch (Exception ex)
{
Common.LogException(ex);
context.Response.Redirect("~/error404.aspx");
}
}
}
private string GetPageName(string url)
{
if(url.Trim() == string.Empty)
return string.Empty;
string[] split = url.Split('/');
string pagename = split[split.Length - 1];
return pagename;
}
}
}
This is an HTTP module so you will need to make the application aware of that it's there by adding an entry into the web.config => System.Web => HttpModules section...