Dot Net Perls

Rewrite URLs With RewritePath - ASP.NET

by Sam Allen

Problem

You have page locations on your site that are easy to remember and convenient for users, but you want to redirect them to a central place in your code. This will save code footprint and encourage a clear and friendly site design to your visitors.

Solution: RewritePath in C#

First, there are many ways of solving this problem, but here we focus on using Global.asax in ASP.NET to programmatically rewrite paths. Rewriting may be thought of as "internal" server-only redirecting. Other rewriting methods include urlMappings. [ASP.NET - urlMappings for Redirects - dotnetperls.com]

Open Global.asax

Global.asax is a useful file for your ASP.NET project and generally you should have one. It contains various event handlers for your project, and to add a new event handler, we simply type it in. ASP.NET will find it and use it on its own. Add an Application_BeginRequest event handler.

<%@ Application Language="C#" %>

<script runat="server">

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
    }

    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown
    }

    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
    }

    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started
    }

    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.
        // Note: The Session_End event is raised...
        // is set to InProc in the Web.config file....
        // or SQLServer, the event is not raised.
    }

    void Application_BeginRequest(object sender, EventArgs e)
    {
        // You typed this
    }

</script>

What does Application_BeginRequest do?

It receives each request that arrives at the ASP.NET application. It will receive requests for images, aspx files, and other files as people try to access those files on your server. Next we will use it to check for a certain kind of request, and then rewrite it.

Example problem

To rewrite paths, you need to know exactly what the request is for, and then what you must change it to. Here I will show some example required rewrites at my coding site. The purpose this rewriting accomplishes is that it allows all the code to be located in one file.

Path requestedRewritten path
/Content/ROT13.aspxdefault.aspx?file=rot13
/Content/About.aspxdefault.aspx?file=about
/Content/Array-Slice.aspxdefault.aspx?file=array-slice

How can I rewrite the paths?

Add code to the Application_BeginRequest event handler that analyzes the HttpContent.Current path string. Detect if it needs to be rewritten, and if so, call RewritePath with the new path. The code that follows performs the rewriting in the table above.

void Application_BeginRequest(object sender, EventArgs e) // 1
{
    HttpContext context = HttpContext.Current; // 2
    string path = context.Request.Path.ToLower(); // 3

    int lastExtension = path.LastIndexOf(".aspx"); // 4
    if (lastExtension == -1)
    {
        return;
    }
    int lastContent = path.LastIndexOf("/content/"); // also 4
    if (lastContent == -1)
    {
        return;
    }
    int lastSlash = path.LastIndexOf('/');
    string key = path.Substring(lastSlash + 1, (lastExtension - lastSlash - 1));

    context.RewritePath("~/default.aspx?file=" + key, false); // 5
}
  1. Runs on each request
    The code above is run on each and every request that comes through ASP.NET. So, you will want to make it relatively fast. The first thing it does above is get the current HttpContext.
  2. What's HttpContext.Current?
    It's a static property that returns the current "context" for the entire application. This means you can use the Request object anywhere, not just on a page file. [C# - Singleton Pattern vs. Static Class - dotnetperls.com]
  3. References Request.Path
    The code above references the request path. That's just a URL basically and we can treat it like any other string.
  4. LastIndexOf used
    Check my IndexOf article for information about the general idea here. These method calls return the positions of the substrings in the |path| string. [C# - IndexOf String Examples - dotnetperls.com]
  5. RewritePath called with substring
    The substring we take first contains the filename (without extension) of the request. We convert that to a query string, and pass in a virtual path to RewritePath.

Does this actually work?

Well, yes. If it didn't, you wouldn't be reading this article because you would be looking at a 404 error. This approach is a dynamic version of urlMappings. Use this sort of method for more complex requirements than urlMappings.

If you need toThen use
Rewrite very few pathsUse urlMappings and type them individually.
Rewrite many paths to query strings
Hook friendly URLs to database
Use RewritePath method. Remember to check for validity.

What else should I know?

Be sure to test frequently. Also I would like to note that many ASP.NET books do not contain this sort of example, and it was very hard for me learn how to do this. However, this approach is much simpler in the end than urlMappings and extremely easy to maintain.

Gotchas

One small problem my implementation of this had when I applied it was that I needed to specify the second argument "false" to RewritePath, which indicates whether to rebase client path. If you specify false, the page the client ends up on will be kept the same as the request would indicate.

Conclusion: rewriting URLs in ASP.NET

Friendly URLs are valued more in search engine placement and are more likely to be bookmarked and shared than "ugly" or hard-to-read URLs. Utilize URL rewriting in ASP.NET in your Global.asax file for a dynamic and easily modifiable mechanism. You will want to change the string handling code and URLs here, but the general technique is effective.

Dot Net Perls
About
Sitemap
ASP.NET
Page_Load Event, AJAX Tutorial
Custom ASHX Handler Tutorial
Cache Examples and Overview
HtmlTextWriter Use
Global Variables Example
New
StartsWith String Examples
GZIP Accept-Encoding Request
© 2008 Sam Allen. All rights reserved.