Freigeben über


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,  Sebastian

  • Anonymous
    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   Daniel

  • Anonymous
    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