Timothy Khouri - SingingEels.com

I subscribe to the "take it apart and rebuild it" approach to learning.

URL Re-Writing (and how to FAKE it!)

SingingEels.com has a custom article engine and a custom blog engine which, like many others, uses a database to store the entries, but accesses them through friendly "named" urls such as : http://www.singingeels.com/Articles/Custom_Controls_And_Control_Builders.aspx

Well, someone emailed me (via the Suggestion Box on Eels) asking how I decided to handle that. So here is my reply email that gives away my cheating secret:

(My Email Reply Starts Here >>) Actually, you have a good question that I'll probably blog about later, but for now I'll let you in on my "url re-writing" secret... I cheat :)

When you submit an article on SingingEels (or a blog entry for that matter), I take the article "Title" text and I strip out all non alpha-numeric characters with a Regex. Basically it's as simple as:

string articleName = Regex.Replace(article.Title, @"[^\w]", "_"); // <-- replace all non-word characters with an underscore.

Then, when I insert the record into the database, I have a field called "ArticleName" to which I will use as the identifyer for the article (so I can pull it up later).
 
Now the only part that remains is knowing when (and how) to pull up that article and display it when someone comes to my site. Well, the "right" way to do this would be to make your own HttpHandler and skim through each request as it comes... but like I said, I cheat, so what I'm about to say is not the "right" way... it's just the easy way :P
 
In the "Global.asax" file in your web applications, you can tap into the "Application_Error" event (really it's a method). This method is called whenever there is an error in your application... including 404 errors for pages with the ".aspx" extension.
 
So, here goes some nasty cheating in ASP.NET:
 
void Application_Error(object sender, EventArgs e)
{
    // Hmmm, an error you say... that's funny, we don't even have
    // a page yet! This tells me that it's probably a "404" error
    // because the file they requested can't be found.
    if (this.Context.Handler == null)
    {
        // Hey ASP.NET, where *WOULD* the file be if one existed?
        string physicalPath = this .Request.PhysicalPath.ToLower();

        // Hmmm... that file *WOULD* be in my "Articles" directory!
        if (physicalPath.StartsWith(global_asax .articlesDirectoryPath))
        {
            // Don't worry lil-ASP.NET, I'll vouch for that request...
            // and I'll point it to the only real page in my "Articles" directory.
            this.Context.Handler = PageParser .GetCompiledPageInstance("~/Articles/Default.aspx",
                 Server.MapPath(
"~/Articles/Default.aspx"), HttpContext .Current);

            // Oh yeah, and ignore that lil 404 error, would ya?
            this.Server.ClearError();
        }
    }
}
 
Now, in my "Default.aspx" page in my articles folder, I check (in the "OnLoad" method) if there is an enrty in the database with the requested "articleName" (which I get from removing the extension from the RequestUrl and then strip out the non-alpha-numeric chars).
 
Then I just populate some basic placeholders and the like with the body of the article (or blog post).
 
Enjoy :P)

Comments

francis said:

Check this site : http://urlrewriter.net/

"UrlRewriter.NET is an open-source, light-weight, highly configurable URL rewriting component for ASP.NET 1.1 and 2.0. UrlRewriter.NET provides similar IIS Rewrite capabilities that the Apache web server provides with mod_rewrite and .htaccess. You don’t need to install an ISAPI Rewrite filter to use the component. Best of all, UrlRewriter.NET is free and licensed with a very permissive MIT-style licence."

# September 13, 2007 10:16 PM

Nullable said:

Cool find... looks like a good amount of code which result in some nifty features :)

# September 13, 2007 10:34 PM

Uwe said:

In projects of mine, I usually associate the 404 handler inside IIS Manager with a custom ASPX page, inside which I can handle _everything_ including ASPX and non-ASPX resources and redirect accordingly.

# September 14, 2007 12:17 AM

Nullable said:

Yeah, that works out well for situations where you have access to IIS, but in scenarios where your hosting provider only allows a "control panel" (or some sort of management shell), it's not as easy.

# September 14, 2007 1:02 AM

.net resource center said:

How can you save two articles with the same title??

# September 14, 2007 5:04 AM

Nullable said:

You can't... two people can't (and shouldn't) write the same article. This is intentionally done.

But, with my blog engine, it only enforces uniqueness bny the author and day, so you can't post the same blog entry two times (by the same user) in one day.

# September 14, 2007 8:33 AM

William said:

I did something similar to this as a proof of concept.  One of the previous employees where I work was relying on *VIRTUAL DOMAINS* and setting them up by hand!  Took me about 5 minutes to hack something up in Global.aspx.  No wonder she got promoted :(

The tip to use HttpHandlers in the future is well noted.

# September 17, 2007 5:01 PM