Rewrite URLs on the Fly - 30 Oct 2009

Also, create multiple login pages and create your own icons for custom controls in the VS .NET controls toolbox.





Rewrite URLs on the Fly

Also, create multiple login pages and create your own icons for custom controls in the VS .NET controls toolbox.


By Jeff Prosise


Q. I'd like to borrow a trick from the Apache handbook and rewrite URLs on the fly so pages that differ only by query strings appear to be separate pages and, therefore, can be bookmarked. Does ASP.NET have something equivalent to Apache's mod_rewrite?


A. Yes, it does. It's called HttpContext.RewritePath, and it's one of the more obscure but potentially useful methods in the portion of the .NET Framework that comprises ASP.NET.


Used internally by ASP.NET to strip session IDs from URLs when cookieless session state is enabled, RewritePath can also be used to "fake" URLs within an application. To demonstrate this, consider an ASPX file that uses a query string parameter named id to decide which of three famous quotations to display (see Figure 1). These URLs invoke the page and display three different quotations:






For simplicity, the quotations are hard-coded into the app rather than obtained from a database or other external data source. However, the principle I demonstrate here is valid regardless of where the page's content originates.





Figure 1. Quotes.aspx uses a query string parameter named "id" to decide which of three famous quotations to display.


Now suppose that you'd like users to be able to display these quotations by typing these "phantom" URLs:






Accomplishing this bit of magic means intercepting every request as it enters ASP.NET's HTTP pipeline and converting URLs of the form .../quotes/pagenn.aspx into URLs of the form .../quotes.aspx?id=nn.


The Global.asax file in Figure 2 shows one way to do the conversion. (Note that this logic could just as easily be packaged in a custom HTTP module.) First it uses an Application_BeginRequest method to trap incoming requests. Then, when it sees a request for /quotes/pagenn.aspx, it uses HttpContext.RewritePath to internally change the path of the requested file to /quotes.aspx?id=nn. It matters not that there is no file named Pagenn.aspx. All that matters is that /quotes.aspx is a valid URL.


Figure 2. This Global.asax file rewrites URLs on the fly using HttpContext.RewritePath.


RewritePath is a powerful component of ASP.NET because it lets you create virtual resource names and map them to physical resource names at run time. Other uses for it include obfuscating path names within your applications for security reasons and using URL munging to encode out-of-band data (such as session IDs) in URLs.


Q. I'm using ASP.NET forms authentication to authenticate visitors to my company's Web site, and I've encountered a roadblock. We have two types of visitors to our site - dealers and customers - and I need to present a different login page to each. I want to redirect to one login page when someone requests a page from the Dealers directory, but redirect to another login page when someone accesses a page in the Customers directory. ASP.NET doesn't let me specify multiple login pages. Is there a workaround?


A. You can simulate multiple login pages by building a single login page that populates itself with controls on the fly. That page can use the ReturnURL query-string parameter to determine which page the user was attempting to access when he or she was redirected to the login page and, thus, determine which controls to create. I've included figures to demonstrate (see Figures 3-6).


To run the sample, create a pair of subdirectories named Dealers and Customers in a virtual root directory on your Web server. Then put DealerHome.aspx (Figure 3) in the Dealers directory and CustomerHome.aspx (Figure 4) in the Customers directory. Next, put Web.config (Figure 5) and LoginPage.aspx (Figure 6) in the virtual root. Then try to open DealersHome.aspx and CustomerHome.aspx in your browser. The login page for dealers includes a "Dealer Number" entry field; the login page for customers does not (see Figure 7).




Hello, dealer!


Figure 3. This is the home page for dealers (DealerHome.aspx).




Hello, customer!


Figure 4. This is the home page for customers (CustomerHome.aspx).





















Figure 5. This Web.config file enables forms authentication and configures the Dealers and Customers subdirectories to require logins.




Please Log In
















User Name:





              RunAt="server" />



              RunAt="server" />





Figure 6. One login page doubles as two by programmatically modifying itself based on the return URL.


Figure 7A. Here are the two login pages: one for dealers ...


Figure 7B. ... and one for customers.


The key code lives in LoginPage.aspx's Page_Init method. Page_Init uses String.IndexOf to determine whether ReturnURL includes the substring "Dealers", indicating that the redirect occurred because the user attempted to fetch a page from the Dealers directory. If the answer is yes, Page_Init programmatically adds a table row and controls for entering a dealer number. The authentication logic in this sample is dirt simple (type "billg" in the user name box and you're in; you want Mr. Gates to be able to view your pages, right?), so you'll want to modify it accordingly. Moreover, you could easily modify Page_Init to support not just two, but any number of, virtual login pages.


Q. When building a custom ASP.NET control, how do I customize the control icon in Visual Studio .NET's controls toolbox?


A. First you create the 16 x 16 bitmap you want Visual Studio .NET to display and store it in a BMP file, taking care to set the pixel in the lower-left corner of the bitmap to the color that you want to be the transparency color. Then you build the BMP into the control assembly as an embedded resource and assign the resource a name of the form namespace.class.bmp, where class is the control's class name and namespace is the namespace in which the control is defined.


If the bitmap is stored in CoolControl.bmp, the control's class name is MyCoolControl, the namespace is Aspnetpro, the source code file is Control.cs, and you're building on the command line with the C# compiler. Here's the command you'd use:


csc /t:library




If you're building the control in Visual Studio .NET instead, name the BMP file Aspnetpro.MyCoolControl.bmp and set the file's build action to "Embedded Resource". To edit the build action, select the BMP file in the Solution Explorer window and go to the Properties window. "Build Action" should appear on the first line of that window.


Note that this is just the tip of the iceberg when it comes to integrating custom server controls into the Visual Studio .NET IDE. Additional customizations can be enacted by applying attributes such as TagPrefix, ToolboxData, and DefaultEvent to the assembly, the control class, and members of that class. Refer to the .NET Framework SDK for additional information regarding these and other integration attributes.


The sample code in this article is available for download.


Jeff Prosise is the author of several books, including Programming Microsoft .NET (Microsoft Press, 2002). He's also a cofounder of Wintellect (, a software consulting and education firm that specializes in .NET. Have a question for this column? Submit queries to [email protected].




Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.