Click here to Skip to main content
15,891,423 members
Articles / Web Development / ASP.NET
Article

URL Mapping / URL Rewriting / Search Engine Friendly URLs / Virtual URLs (ASP.NET)

Rate me:
Please Sign up or sign in to vote.
4.33/5 (25 votes)
20 Apr 2007CPOL1 min read 216.3K   2.6K   107   48
URL Mapping / URL Rewriting / Search Engine Friendly URLs / Virtual URLs with postbacks in ASP.NET C# (Without hardcoding in Web.Config)

Introduction

(ASP.NET, C#, Visual Studio 2005)

Hi folks; Recently, I built a custom Content Management Software for a website. The client wanted the page contents to be served from database by a page ShowContents.aspx?ContentID=XX.
The main requirements were as follows:

  • Search engine friendly URLs (i.e. They would like "/finance/loan.aspx" instead of "ShowContents.aspx?ID=23").
  • Hardcoding URLs in Web.Config's URLMapping section was not an option, as there were no physical pages to map to.
  • Postback should still work on all these virtual URLs.
  • References to the images, css files, and themes should stay intact.

Solution

After a day's research, I came up with this really simple solution. I thought I should sum up the knowledge collected from various sources and make it public for everyone to benefit.
You can integrate following steps in to your existing ASP.NET project, or you can create a new one.

STEP 1

  • Create "ShowContents.aspx", that serves content based on the ContentID passed in the QueryString.
  • To enable postbacks to the raw URL in the Page_Load() event of ShowContents.aspx, insert following line Context.RewritePath(Path.GetFileName(Request.RawUrl)); // needs System.IO

STEP 2

  • Capture the URL requested by the user in the Application_BeginRequest() event of Global.asax.
  • Find the ID of the content from database that is relevant to this URL
  • ReWritePath to ShowContents.aspx?ContentID=XX. The user will see requested URL in the address bar with the desired content.
  • Any files that physically exist on the server will still get served as usual.

Using the code

// STEP 1 (ShowContents.aspx)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This page displays contents from a database for a ContentID. This file
// must contain the following line in it's Page_Load() event.
Context.RewritePath(Path.GetFileName(Request.RawUrl)); //needs System.IO

// STEP 2 (Global.asax)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Following code goes in your Global.asax file, in the root directory of
// the project. This file captures the incoming requests' URL, gets the 
// Content ID of the content related to the URL and redirects the user to
// ShowContents.aspx?ContentID=XX. While the user still sees the requested 
// URL in the address bar.

    <%@ Import Namespace="System.IO" %>
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        // If the requested file exists
        if (File.Exists(Request.PhysicalPath))
            { 
                // Do nothing here, just serve the file
            }
        // If the file does not exist then
        else if (!File.Exists(Request.PhysicalPath))
            {
            // Get the URL requested by the user
            string sRequestedURL = Request.Path.Replace(".aspx", "");
            
            // You can retrieve the ID of the content from database that is 
            // relevant to this requested URL (as per your business logic)
            int nId = 0;        
            ////// nId = GetContentIDByPath(sRequestedURL); \\\\\

           // The ShowContents.aspx page should show contents relevant to 
           // the ID that is passed here
            string sTargetURL = "~/ShowContents.aspx?ContentID=" + nId.ToString();

            // Owing to RewritePath, the user will see requested URL in the
        // address bar
            // The second argument should be false, to keep your references
        // to images, css files
            Context.RewritePath(sTargetURL, false);
        }
    }
//  That's all! :-) 

Hope this helps you save time on researching various sources. You might like to download the zip file containing a sample VS 2005 project.

Feedback is welcome and appreciated.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Manu Agrawal is a .NET developer living in the USA.
He has good professional web development experience (mainly in ASP.NET, C#). He enjoys developing high performance and secure websites.
He holds a master's degree in E-Commerce and Management from London, UK.

Comments and Discussions

 
GeneralRe: Validators and WebResource.axd in general Pin
mplusplus3-May-07 5:57
mplusplus3-May-07 5:57 
AnswerRe: Validators and WebResource.axd in general Pin
Andrei Ion Rînea21-May-07 6:09
Andrei Ion Rînea21-May-07 6:09 
GeneralVirtual Domains Pin
Paulo Moreno30-Apr-07 9:36
Paulo Moreno30-Apr-07 9:36 
AnswerRe: Virtual Domains Pin
mplusplus30-Apr-07 9:49
mplusplus30-Apr-07 9:49 
GeneralUrl Parsing Pin
Tim McCurdy28-Apr-07 4:32
Tim McCurdy28-Apr-07 4:32 
GeneralHttpHandler Pin
Jasmine250125-Apr-07 8:42
Jasmine250125-Apr-07 8:42 
GeneralRe: HttpHandler Pin
mplusplus25-Apr-07 9:33
mplusplus25-Apr-07 9:33 
GeneralRe: HttpHandler Pin
Jasmine250125-Apr-07 10:39
Jasmine250125-Apr-07 10:39 
That is a very good point - anything that doesn't have to go through that ASP engine, is a Good Thing. In your case, adding an HttpHandler is simply overkill - all the things you want to alter are already going through the ASP engine. Mine actually responds to all requests that aren't aspx pages, and now that I think of it, that's why I didn't use something similar to your method in the first place. I had a slightly different requirement than your site. In my case, I wanted to handle all files with my custom handler, so I had to re-map the file type *.* to be handled by the ASP engine. This means all requests to my site are going through the ASP engine. That's a clear performance problem, but it adds the ability for me write custom file handling code very easily. Your method is better, if the files you are handling are aspx files, but what would you do if you needed to serve up music, video, and various application-specific documents (like .doc, .ppt, etc)?

The reason I ask is because it took me a long time to get the HttpHandler to work correctly, and nobody out there was able to help me. I finally figured it out myself, but I was amazed at the sheer number of people who basically said to do it another way. Your method seems to be a popular alternative, and one that most people seem to use when they find out that HttpHandlers are tricky to get right.

(I'm basically building a compliance system... such that users from different companies can only get the documents that are approved by their compliance department. There is a possibility of us having multiple versions of the same document, one for each company, but we want the URLs to be the same so people can share them between companies, and everyone still sees the correct versions. We want the server to serve up the correct version based on the user's login, and we wanted to send back an error if the person is not logged in, or if the company does not have an approved version of the requested document. This had to work with all requests for the document, regardless of the actual URL used.)

"Quality Software since 1983!"
http://www.smoothjazzy.com/ - see the "Programming" section for freeware tools and articles.

GeneralRe: HttpHandler Pin
Steve Riggall12-Feb-09 10:06
Steve Riggall12-Feb-09 10:06 
Generalurlrewriter.net Pin
edonistart23-Apr-07 19:12
edonistart23-Apr-07 19:12 
GeneralProblems with postback and UpdatePanel Pin
marco vervoort12-Apr-07 2:07
marco vervoort12-Apr-07 2:07 
AnswerRe: Problems with postback and UpdatePanel Pin
mplusplus2-May-07 4:20
mplusplus2-May-07 4:20 
Generalthanks for the postback thingy Pin
robert_fairbrother9-Apr-07 22:37
robert_fairbrother9-Apr-07 22:37 
GeneralCool Pin
Ben Daniel9-Apr-07 20:50
Ben Daniel9-Apr-07 20:50 
GeneralRe: Cool Pin
mplusplus14-Apr-07 12:06
mplusplus14-Apr-07 12:06 
GeneralRe: Cool Pin
stixoffire7-Oct-07 20:46
stixoffire7-Oct-07 20:46 
Generalurlrewriting.net Pin
matt from ne8-Apr-07 17:56
matt from ne8-Apr-07 17:56 
QuestionA problem with extensions Pin
p daddy8-Apr-07 10:25
p daddy8-Apr-07 10:25 
AnswerRe: A problem with extensions Pin
mplusplus8-Apr-07 10:35
mplusplus8-Apr-07 10:35 
GeneralRe: A problem with extensions Pin
Furty8-Apr-07 15:09
Furty8-Apr-07 15:09 
AnswerWell actually you can sorta capture requests for extensionless files Pin
volkan.ozcelik9-Apr-07 8:19
volkan.ozcelik9-Apr-07 8:19 
GeneralRe: Well actually you can sorta capture requests for extensionless files Pin
danielkennedy9-Apr-07 20:58
danielkennedy9-Apr-07 20:58 
GeneralRe: Well actually you can sorta capture requests for extensionless files Pin
volkan.ozcelik10-Apr-07 21:45
volkan.ozcelik10-Apr-07 21:45 
GeneralRe: Well actually you can sorta capture requests for extensionless files Pin
John9703018-Apr-07 9:11
John9703018-Apr-07 9:11 
AnswerRe: A problem with extensions Pin
stixoffire7-Oct-07 20:44
stixoffire7-Oct-07 20:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.