Teun.ToString()

by Teun Duynstee [Macaw]

<December 2008>
SuMoTuWeThFrSa
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910


Navigation

Subscriptions

News

I discontinued this blog. I now post at: www.TeunToString.net



Download Finch PocketBlogger

Post Categories

Article Categories



Tuesday, February 15, 2005 - Posts

VirtualPathProvider adventures: trying to get XInclude to work on web.config files

Disclaimer: this is all tested on Beta 1 code.

When I had the VirtualPathProvider sample from Scott Guthrie working, I wanted to create something useful with this technique. The idea I had was building XInclude support for web.config files. This would allow to split up the several segments of a config file over several physical files. Some ConfigurationSectionHandlers offer some support for reading values from external files (like NameValueFileSectionHandler), but often, this support is not sufficient.

What I would like to do is splitting web.config into parts that are the sole responsibility of the development team (and which are automatically deployed with newer versions) and parts that are the domain and responsibility of the system administrators. The web.config should then be constructed before it was even read by the AppDomain. I figured that by using the VirtualPathProvider model, I could just subclass from the default provider (called MapPathBasedVirtualPathProvider) and change it only for the cases where the GetFile method is called for files that are called web.config. Only in those cases, I would then open the file myself, scan it for any xi:include elements and replace them by the content they refer to. Easy. So I thought.

First, it turns out that MapPathBasedVirtualPathProvider is an internal class, so no subclassing. No harm done: when our provider is initialized, the system passes us the existing provider to allow us to do some delegation to it. So, to start up I built a wrapper class that delegates all of its calls to the previous provider. Code now looks like this:

 public class ConfigPathProvider : VirtualPathProvider
 {
  protected VirtualPathProvider _previous = null;
  public ConfigPathProvider(){}

  // The system initializes our provider after we have registered it
  public override void Initialize(VirtualPathProvider previous)
  {
   _previous = previous;
  }

  public override bool DirectoryExists(string virtualDir)
  {
   return _previous.DirectoryExists(virtualDir);
  }

  public override bool FileExists(string virtualPath)
  {
   return _previous.FileExists(virtualPath);
  }

  public override VirtualDirectory GetDirectory(string virtualDir)
  {
   return _previous.GetDirectory(virtualDir);
  }

  public override VirtualFile GetFile(string virtualPath)
  {
   return _previous.GetFile(virtualPath);
  }

  /* And some more methods, you get the point */

}

The AppInitialize is set up in a different class, to allow this class to be in a reusable library. Putting up break points on all of the methods now allows us to see how this works. Some findings:

  • web.config is not accessed through the provider (boohoo, this immediately kills my mini-project)
  • not all of the other file requests go through the provider anyway. This is because we delegate to the MapPathBasedVirtualPathProvider. It turns out that the GetDirectory method returns an instance of MapPathBasedVirtualDirectory. When ASP.NET iterates through the files or directories within that directory, the MapPathBasedVirtualDirectory will return MapPathBasedVirtualFile instances that will directly access the filesystem without using the VirtualPathProvider to instantiate the VirtualFile instance. This is a bug, because it breaks the concept of delegating to the previous provider (MSFT: if you are reading this: the problem is in MapPathBasedVirtualPathEnumerator.Current)

 

Wrapping it up: VirtualPathProviders can be used for serving code and aspx templates from a custom source, like a database. It will not work for images and other resources that are not mapped to ASP.NET, but it will also not work for the web.config file. This is a pity, because that seemed like a promising application. I think that the debugging experience with code being served from the database may be very special as well. ;)

 

posted Tuesday, February 15, 2005 1:32 PM by TeunD with 0 Comments

VirtualPathProvider adventures: how to wire it up

Disclaimer: all of my findings are on the Beta 1 release

In my previous post, I told about the VirtualPathProvider that is part of the ASP.NET 2.0 architecture. Scott Guthrie told about it in his presentation at the European ASP.NET roadshow. There is a sample online on his site (it's the one from VSLive Orlando). In the sample, a website is created that contains only C# files in the Code directory and an Access database. The only table in the MDB file looks like this:

Note that the database actually contains all of the code for the ASPX pages and the code-behinds that would normally be on the file system. In the Code directory, there is a DBFileProvider.cs class. This class derives from System.Web.Hosting.VirtualPathProvider and whenever the ASP.NET engine needs to read a “file”, it actually calls into this class.

That is all very cool; you could use this kind of functionality very nicely in CMS's (every developer still works on his own CMS that will be better and more user friendly? Of course you are!). Here is the strange part: there is no web.config. So how does the ASP.NET runtime know which class to load? In the sample from Scott, the trick is done in a static method called AppInitialize(). If the Code directory in your project contains a class that has a method with this signature:

  public static void AppInitialize()

the engine will call this method when the application is starting up. If you have more than one class with this method, VS.NET 2005 will give a build error. The in this method you can register the provider:

   WebConfigXInclude.ConfigPathProvider fileProvider = new WebConfigXInclude.ConfigPathProvider();
   HostingEnvironment.RegisterVirtualPathProvider(fileProvider);

After finding out how the registration of the provider works, I concluded that this was done in this way to allow the web.config file to be loaded through the VirtualPathProvider as well. You can't configure the provider for reading the configuration in the configuration. That figures. However, this turns out not to be the case. I will write about my unfruitful attempts to run from a virtual web.config in my next post.

What I really don't understand: why did the very smart guys developing the ASP.NET engine decide to use a “special method name”? They could have used a special interface. What exactly will happen when you have a current .NET 1.1 application that contains several classes with an AppInitialize() method in them? Or only one that expects an HttpContext available?

posted Tuesday, February 15, 2005 12:29 PM by TeunD with 1 Comments




Powered by Dot Net Junkies, by Telligent Systems