Advanced Navigation

Websites tend to be organic—they grow and change over time. This can create problems when other applications link to your application. You need some way of modifying your website without breaking all the existing links to it.

Remapping URLs
The simplest way to remap a URL is to specify the remapping in your application’s web configuration file.

<configuration>
<system.web>
<urlMappings>
<add
url=”~/Home.aspx”
mappedUrl=”~/Default.aspx”/>
</urlMappings>
</system.web>
</configuration>

The mappedUrl attribute can contain query strings. However, it cannot contain wildcards. You can use the <urlMappings> element only when performing simple page-topage mappings. After you add the web configuration file 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.


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. You can use the following 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.

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.

Using the VirtualPathProvider Class
The VirtualPathProvider class enables you to abstract the pages in a web application from the file system. In other words, it enables you to store your ASP.NET pages any way you please. For example, you can use the VirtualPathProvider class to store all the pages in your application in a database. This would be an appropriate choice when you need to build a CMS. If you store pages in a database, then users can update the pages easily in an application through an HTML form interface and save the changes to the database. The sample application at the end of this book uses the VirtualPathProvider class to store code samples in the database. Users of the website can execute the code samples
directly from the database.

Limitations of the VirtualPathProvider Class
Unfortunately, you can’t use the VirtualPathProvider with every type of file. In particular, the following types of files must always be located on the file system:
  • Global.asax file
  • Web.Config files
  • App_Data folder
  • App_Code folder
  • App_GlobalResources folder
  • App_LocalResource folders
  • Bin folder

Every other type of file is fair game. This includes ASP.NET pages, User Controls, Themes, and Master Pages.

Understanding the VirtualPathProvider Class
The VirtualPathProvider class is a MustInherit (abstract) class. It contains the following methods, which you can override:
  • CombineVirtualPaths()—Returns a combined path from two paths.
  • DirectoryExists()—Returns true when a directory exists.
  • FileExists()—Returns true when a file exists.
  • GetCacheDependency()—Returns a cache dependency object that indicates when a file has been changed.
  • GetCacheKey()—Returns the key used by the cache dependency.
  • GetDirectory()—Returns a VirtualDirectory.
  • GetFile()—Returns a VirtualFile.
  • GetFileHash()—Returns a hash of the files used by the cache dependency.
  • OpenFile()—Returns the contents of a file.

Typically, you override the FileExists() and GetFile() methods to retrieve a file from your data store. If you want to represent directories, then you also need to override the DirectoryExists() and GetDirectory() methods. Notice that several of these methods are related to caching. VirtualPathProvider needs to know when a file has been modified so that it can retrieve the new version of the file and compile it. By default, the ASP.NET Framework uses a file dependency to determine when
a file has been modified on the hard drive. However, in this situation a SqlCacheDependency is used because the files will be stored in a database.

VirtualPathProvider also includes a very useful property:
  • Previous—Returns the previously registered VirtualPathProvider. The Previous property enables you to use the default VirtualPathProvider. For example, if you want to store some files in the file system and other files in the database, then you can use the Previous property to avoid rewriting all of the logic for working with files in the file system.

The GetFile() method returns an instance of the VirtualFile class. When using the VirtualPathProvider, you must create a new class that inherits from the VirtualFile class. This class contains the following properties:
  • IsDirectory—Always returns False.
  • Name—Returns the name of the file.
  • VirtualPath—Returns the virtual path of the file.
The VirtualFile class also contains the following method:
  • Open()—Returns the contents of the file.

Typically, when creating a class that inherits from the VirtualFile class, you override the Open() method. For example, we’ll override this method to get the contents of a file from a database table in the code sample built in this section.

The GetDirectory() method returns an instance of the VirtualDirectory class. This class contains the following properties:
  • Children—Returns all the files and directories that are children of the current directory.
  • Directories—Returns all the directories that are children of the current directory.
  • Files—Returns all the files that are children of the current directory.
  • IsDirectory—Always returns True.
  • Name—Returns the name of the directory.
  • VirtualPath—Returns the virtual path of the directory.

There is another class in the ASP.NET Framework that you’ll want to use when working with the VirtualPathProvider class. The VirtualPathUtility class contains several useful methods for working with virtual paths:
  • AppendTrailingSlash()—Returns a path with at most one forward slash appended to the end of the path.
  • Combine()—Returns the combination of two virtual paths.
  • GetDirectory()—Returns the directory portion of a path.
  • GetExtension()—Returns the file extension of a path.
  • GetFileName()—Returns the file name from a path.
  • IsAbsolute()—Returns True when a path starts with a forward slash.
  • IsAppRelative()—Returns True when a path starts with a tilde (~).
  • MakeRelative()—Returns a relative path from an application-relative path.
  • RemoveTrailingSlash()—Removes trailing slash from the end of a path.
  • ToAbsolute()—Returns a path that starts with a forward slash.
  • ToAppRelative()—Returns a path that starts with a tilde (~).



By taking advantage of the VirtualPathUtility class, you can avoid doing a lot of tedious string parsing on paths.

Registering a VirtualPathProvider Class
Before you can use an instance of the VirtualPathProvider class, you must register it for your application. You can register a VirtualPathProvider instance with the
HostingEnvironment.RegisterVirtualPathProvider() method.

You need to register VirtualPathProvider when an application first initializes. You can do this by creating a shared method named AppInitialize() and adding the method to any class contained in the App_Code folder. The AppInitialize() method is automatically called by the ASP.NET Framework when an application starts.

No comments:

Post a Comment