Remapping URLs


The simplest way to remap a URL is to specify the remapping in your application's web configuration file. For example, the web configuration file in Listing 19.1 remaps the Home.aspx page to the Default.aspx page.

Listing 19.1. Web.Config

<?xml version="1.0"?> <configuration> <system.web>   <urlMappings>     <add       url="~/Home.aspx"       mappedUrl="~/Default.aspx"/>   </urlMappings> </system.web> </configuration> 

The configuration file in Listing 19.1 contains a <urlMappings> element. This element can contain one or more elements that remap a page from a URL to a mapped Url.

CD Note

The code samples in this section can be found in the UrlMappingsApp application on the CD that accompanies this book.


The mappedUrl attribute can contain query strings. However, it cannot contain wildcards. You can use the <urlMappings> element only when performing simple page-to-page mappings.

After you add the web configuration file in Listing 19.1 to your application, any requests for the Home.aspx page are modified automatically to requests for the Default.aspx page. It doesn't matter whether the Home.aspx page actually exists. If the Home.aspx page does exist, you can never open the page.

Note

The tilde character (~) has a special meaning when used with a path. It represents the current application root. A forward slash (/) at the start of a URL, on the other hand, represents the website root.

You can use the tilde only with properties of ASP.NET controls. For example, you can use it with the ASP.NET Image control's ImageUrl property, but you cannot use it with the HTML <img> src attribute.

In code, you can use the tilde character with a path by using the Page.ResolveUrl() method. This method automatically expands the tilde to the application root.


When working with remapped URLs, you often need to determine the original URL that a user requested. For example, you might want to display a message that tells users to update their bookmarks (favorites) to point to the new URL.

There are three properties you can use to determine the current URL:

  • Request.RawUrl Returns the original URL (before being remapped).

  • Request.Path Returns the current URL (after being remapped).

  • Request.AppRelativeCurrentExecutionFilePath Returns the application relative URL (after being remapped).

The last property automatically replaces the name of the web application with a tilde (~) character.

For example, the Default.aspx page in Listing 19.2 illustrates all three properties.

Listing 19.2. Default.aspx

[View full width]

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD /xhtml11.dtd"> <script runat="server">     Private Sub Page_Load()         If String.Compare(Request.Path, Request.RawUrl, True) <> 0 Then             lblMessage.Text = "The URL to this page has changed, " _                 & "please update your bookmarks."         End If     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         html         {             font:14px Georgia,Serif;         }         .message         {             border:Dotted 2px red;             background-color:yellow;         }     </style>     <title>Default Page</title> </head> <body>     <form  runat="server">     <div>     <h1>The Default Page</h1>     <p>     <asp:Label                  Css         Runat="server" />     </p>     The original request was for:     <blockquote>         <%=Request.RawUrl%>     </blockquote>     which got remapped to:     <blockquote>         <%= Request.Path %>     </blockquote>     and the application relative version is:     <blockquote>         <%= Request.AppRelativeCurrentExecutionFilePath %>     </blockquote>     </div>     </form> </body> </html> 

If you request the Home.aspx page, the request is remapped to the Default.aspx page by the web configuration file in Listing 19.1. The Page_Load() event handler displays a message asking users to update their bookmarks when the RawUrl does not match the path (see Figure 19.1).

Figure 19.1. Remapping the Home page.


Each property displayed in the body of the page displays a different value:

Request.RawUrl = /UrlMappingsApp/Home.aspx Request.Path = /UrlMappingsApp/Default.aspx Request.AppRelativeCurrentExecutionFilePath = ~/Default.aspx


Creating a Custom UrlRemapper Module

The <urlMappings> configuration element discussed in the previous section performs a very simple task. It remaps one page to another. However, you'll quickly discover that you need to perform more complex remappings.

For example, imagine that you have a database that contains a table of product categories and a table of products. You want your website's users to request a URL that contains a product category and be able to see matching products. For example, if someone requests the /Products/Soda.aspx page, you want to display all the products in the Soda category. If someone requests the /Products/Milk.aspx page, you want to display all the products in the Milk category.

In that case, you need to use a wildcard when matching URLs. When someone requests any path that matches the pattern /Products/*, you want to redirect the user to a page where you can display matching products for the category specified in the path.

In this section, we create a custom HTTP module that remaps one URL to another. The module supports regular expression matching. Therefore it supports wildcard matches.

CD Note

The code samples in this section are located in the UrlRemapperApp application on the CD that accompanies this book.


The code for the custom modulenamed UrlRemapperis contained in Listing 19.3.

Listing 19.3. UrlRemapper.vb

Imports System Imports System.Web Imports System.Xml Imports System.Web.Caching Imports System.Text.RegularExpressions Namespace AspNetUnleashed     Public Class UrlRemapper         Implements IHttpModule         Public Sub Init(ByVal app As HttpApplication) Implements IHttpModule.Init             AddHandler app.BeginRequest, AddressOf app_BeginRequest         End Sub         Public Sub app_BeginRequest(ByVal s As Object, ByVal e As EventArgs)             ' Get HTTP Context             Dim app As HttpApplication = CType(s, HttpApplication)             Dim context As HttpContext = app.Context             ' Get current URL             Dim currentUrl As String = context.Request.AppRelativeCurrent ExecutionFilePath             ' Get URL Mappings             Dim urlMappings As XmlDocument = GetUrlMappings(context)             ' Compare current URL against each URL from mappings file             Dim nodes As XmlNodeList = urlMappings.SelectNodes("//add")             For Each node As XmlNode In nodes                 Dim url As String = node.Attributes("url").Value                 Dim mappedUrl As String = node.Attributes("mappedUrl").Value                 If Regex.Match(currentUrl, url, RegexOptions.IgnoreCase).Success Then                     context.RewritePath(mappedUrl)                 End If             Next         End Sub         Private Function GetUrlMappings(ByVal context As HttpContext) As XmlDocument             Dim urlMappings As XmlDocument = CType(context.Cache("UrlMappings"), XmlDocument)             If urlMappings Is Nothing Then                 urlMappings = New XmlDocument()                 Dim path As String = context.Server.MapPath("~/UrlMappings.config")                 urlMappings.Load(path)                 Dim fileDepend As CacheDependency = New CacheDependency(path)                 context.Cache.Insert("UrlMappings", urlMappings, fileDepend)             End If             Return urlMappings         End Function         Public Sub Dispose() Implements System.Web.IHttpModule.Dispose         End Sub     End Class End Namespace 

Notice that the class in Listing 19.3 implements the IHttpModule interface. An HTTP module is a special class that executes whenever you make a page request. HTTP Modules are discussed in detail in Chapter 25, "Working with the HTTP Runtime."

The module in Listing 19.3 includes an Init() method. This method adds an event handler for the Application BeginRequest event. The BeginRequest event is the first event that is raised when you request a page.

The BeginRequest handler gets a list of URL remappings from an XML file named UrlMappings.config. The contents of this XML file are cached in memory until the UrlMappings.config file is changed on the hard drive.

Next, the module iterates through each remapping from the XML file and performs a regular expression match against the current URL. If the match is successful, then the Context.RewritePath() method is used to change the current path to the remapped path.

Before you can use the module in Listing 19.3 in an application, you must first register the module in your application's web configuration file. The web configuration file in Listing 19.4 contains an <httpModules> element that includes the UrlRemapper module.

Listing 19.4. Web.Config

<?xml version="1.0"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web>   <httpModules>     <add       name="UrlRemapper"       type="AspNetUnleashed.UrlRemapper" />   </httpModules> </system.web> </configuration> 

A sample UrlMappings.config file is contained in Listing 19.5.

Listing 19.5. UrlMappings.config

<?xml version="1.0"?> <urlMappings>   <add     url="~/Home.aspx"     mappedUrl="~/Default.aspx" />   <add     url="/Products/.*"     mappedUrl="~/Products/Default.aspx" /> </urlMappings> 

The XML file in Listing 19.5 contains two remappings. First, it remaps any request for the Home.aspx page to the Default.aspx page. Second, it remaps any request for any page in the Products directory to the Default.aspx page located in the Products folder.

The second mapping uses a regular expression to match the incoming URL. The .* expression matches any sequence of characters.

The Default.aspx page in the Products folder is contained in Listing 19.6.

Listing 19.6. Products/Default.aspx

[View full width]

<%@ Page Language="VB" %> <%@ Import Namespace="System.IO" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD /xhtml11.dtd"> <script runat="server">     Private  Sub Page_Load()         If Not Page.IsPostBack Then             Dim category As String = Path.GetFileNameWithoutExtension(Request.RawUrl)             ltlCategory.Text = category             srcProducts.SelectParameters("Category").DefaultValue = category         End If     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         .grid td,.grid th         {             padding:4px;             border-bottom:solid 1px black;         }     </style>     <title>Products</title> </head> <body>     <form  runat="server">     <div>     <h1>     <asp:Literal                  runat="server" />     </h1>     <asp:GridView                  DataSource         Css         GridLines="None"         AutoGenerateColumns="false"         Runat="server">         <Columns>         <asp:BoundField             HeaderText="Product Name"             DataField="Name" />         <asp:BoundField             HeaderText="Price"             DataField="Price"             DataFormatString="{0:c}" />         </Columns>     </asp:GridView>     <asp:SqlDataSource                  ConnectionString="<%$ ConnectionStrings:Products %>"         SelectCommand="SELECT Products.* FROM Products             JOIN Categories ON Products.CategoryId=Categories.Id             WHERE Categories.Name=@Category"         Runat="server">         <SelectParameters>         <asp:Parameter Name="Category" />         </SelectParameters>     </asp:SqlDataSource>     </div>     </form> </body> </html> 

The Page_Load() event handler in Listing 19.6 grabs the path of the original request, using the Request.RawUrl property. Next, it extracts the filename from the path, using the System.IO.Path.GetFileNameWithoutExtension() method. Finally, it assigns the name of the page (the category name) to a Label and SqlDataSource control. Products that match the category are displayed in a GridView control.

For example, if you request the /Products/Soda.aspx page, then all the products in the Soda category are displayed (see Figure 19.2). If you request the /Products/Milk.aspx page, then all products in the Milk category are displayed.

Figure 19.2. Displaying matching products.





ASP. NET 2.0 Unleashed
ASP.NET 2.0 Unleashed
ISBN: 0672328232
EAN: 2147483647
Year: 2006
Pages: 276

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net