Daily .Net Feeds - ASP.Net 2.0 - Advanced - Day 15
Hi Everyone,
Welcome back!!!
As mentioned yesterday, today we will be wrapping up with the discussion about the ASP.Net 2.0 compilation machinery with the discussion about virtual path providers.
Virtual Path Providers:
Before the advent of ASP.NET 2.0, a source ASP.NET page could be only an .aspx file deployed on the server and located in a particular folder. A one-to-one correspondence is required between .aspx resources and files on disk. In ASP.NET 2.0, the virtual path provider mechanism allows you to virtualize a bunch of files and even a structure of directories. You can abstract web content away from the physical structure of the file system. Created to serve the needs of SharePoint (the next version of SharePoint when ASP.Net 2.0 was being designed was to be built on top of ASP.NET 2.0) virtual path providers prove extremely useful to ASP.NET developers too. For example, you can register a path provider and serve ASP.NET the source code of your pages reading from a database. (Yes, this is just what SharePoint does with its earlier version and will do, based on ASP.NET 2.0.)
Structure of a Virtual Path Provider:
A virtual path provider (VPP) is a class that inherits from the VirtualPathProvider class and implements a virtual file system for a Web application. In such a virtual file system, you're essentially using files and directories that a custom data store other than the file system will provide. Most files involved with the processing of an ASP.NET request can be stored in a virtual file system. The list includes ASP.NET pages, themes, master pages, user controls, custom resources mapped to a build provider, and static Web resources such as HTML pages and images.
A VPP can't serve global resources—such global.asax and web.config—and the contents of reserved folders—such as Bin, App_Code, App_Data, App_GlobalResources, and any App_LocalResources. Below table details the members to override in a sample VPP component.
Member |
Description |
CombineVirtualPaths |
Combines a base path with a relative path to return a complete path to a virtual resource |
DirectoryExists |
Indicates whether a directory exists in the virtual file system |
FileExists |
Indicates whether a file exists in the virtual file system |
GetCacheDependency |
Creates a cache dependency based on the specified virtual paths |
GetCacheKey |
Returns a cache key to use for the specified virtual path |
GetDirectory |
Gets a reference to a VirtualDirectory-derived class that represents the virtual directory the requested resource is mapped to |
GetFile |
Gets a reference to a VirtualFile derived class that represents the virtual file the requested resource is mapped to |
GetFileHash |
Returns a hash of the specified virtual paths |
Previous |
Protected property, gets a reference to a previously registered VPP object to ensure that the resource can be resolved either by a registered VPP or the default one |
When writing a custom VPP, it is important that you override GetFile and GetDirectory and use the Previous property carefully. Here's an example:
public override VirtualFile GetFile(string virtualPath) { if (IsPathVirtual(virtualPath)) return new YourVirtualFile(virtualPath, this); else return Previous.GetFile(virtualPath); } |
In the preceding code, IsPathVirtual is a private function that simply establishes whether your VPP is able to process the virtual path. If not, you pass the request down to the next VPP in the ASP.NET chain. If you omit the call to Previous, the request won't be processed.
private bool IsPathVirtual(string virtualPath) { // For example // Check the virtual path against your data store } |
Structure of a Virtual File:
A virtual path provider works by taking URLs and checking whether a VPP is registered to handle that URL. If so, the VPP is given a chance to return the ASP.NET source for that path. A VPP returns the source of a virtual path through an object that inherits from the class VirtualFile. Following table details the members to override in a virtual file class.
Member |
Description |
IsDirectory |
Indicates whether this is a virtual resource that should be treated as a file |
Name |
Gets the display name of the virtual file |
VirtualPath |
Gets the path of the virtual file |
Open |
Returns a read-only stream that refers to the contents of the requested resource |
The key thing to do when writing a custom virtual file class is to override the Open method and make it return a read-only stream to the contents of the virtual resource. In the Open method, you use the virtual path as the key to access the data store and retrieve the source code.
Registering a Virtual Path Provider:
Unlike most providers, a virtual path provider is not registered through the web.config file. You can register your VPP either in the Application_Start global event or by adding a static AppInitialize method to some class deployed in App_Code. Here's a sample class you can drop in App_Code to register a VPP:
public static class AppStart { public static void AppInitialize() { // Add a new VPP to the chain MyPathProvider vpp = new MyPathProvider(); HostingEnvironment.RegisterVirtualPathProvider(vpp); } } |
The name of the surrounding class is arbitrary; the name and signature of AppInitialize are not :-). If multiple static methods with this name exist in the different classes stored in App_Code, you get a compile error.
Important Note: It is essential that a virtual path provider be registered prior to any page parsing or compilation. If a path provider is registered in other points in the application (for example, web.config) or page life cycle, some unexpected results may show up. There's no syntax requirement that prevents you from registering a VPP, say, in Page_Load. However, if the VPP is registered after the page assembly has been generated, there's no way to invalidate the link between that page and that assembly. As a result, when requesting that page, the VPP will be bypassed. It still makes sense to register a VPP from within a page event, but only if you do that from a page that is not designed to be served by the VPP and that is invoked prior to any page served by the VPP. As you can see, it might not be a common situation and so the above method is usually used.
That's it for today. Thanks for joining!!! See you tomorrow. Tomorrow we will start discussing about HTTP Handlers and Modules.
Thanks,
Sukesh Khare
Coordinator Daily .Net Feed Program
Comments
- Anonymous
August 01, 2007
I use virtualpathprovider, which works fine with all my cs files in app_code. But now I need deploy the site to a customer's machine, I don't want to deploy the source code for sure. But after I compile the site with appnet_compiler -f -v / c:deploy I can not run it, for example, a page like /page/home.aspx, it is a virtual page served by virtualpathprovider, before compilation, it works fine, after compilation, it shows Server Error in '/' Application.
The resource cannot be found. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly. Requested URL: /page/home.aspx it seems after compilation, it treats that page as static page, or virtualpathprovider doesn't kick in for some reason. Any idea? thanks
Anonymous
August 06, 2007
Hey, when it's going further? ;-) I can't wait for new parts of this GREAT articles. Greets, SebastianAnonymous
August 08, 2007
Hi, Sukesh is currently busy which will unfortunaletely delay this feed. He though indends to continue the Daily .Net Feeds. Best regards DanielAnonymous
August 08, 2007
@davidw Precompilation does not work with VirtualPathProviders. I think it could have been made to work in theory, but there were some non-trivial issues, and scheduling made us decide not to support it. http://blogs.msdn.com/davidebb/archive/2005/11/27/overriding-asp-net-combine-behavior-using-a-virtualpathprovider.aspx Best regards Daniel