The VirtualPathProvider class provides some options when building websites. One of the most common is to be able to server ASPX/ASCX requests from embedded resources in an assembly.
A good place to start is from a CodeProject article that address this issue.
First, instead of using hardcode assemblies/paths/etc, a few properties were attached.
#region Properties
public String VirtualPath { get; set; }
public String VirtualFileSystemAssembly { get; set; }
public String VirtualFileSystemBaseNamespace { get; set; }
#endregion
Also, instead of just assuming that a file might exist in the assembly if the virtual paths match – because we might want to serve file from multiple assemblies on the same virtual path – the code will check if the resource exists in the assembly.
private bool DoesExistInVirtualPath(string virtualPath)
{
if (!IsInVirtualPath(virtualPath))
return false;
Assembly assembly = GetAssemblyReference();
if (assembly != null)
{
String[] resources = assembly.GetManifestResourceNames();
String resourceName = ConstructAssemblyResourceName(virtualPath);
if (resources != null && resources.Contains(resourceName, StringComparer.InvariantCultureIgnoreCase))
return true;
}
return false;
}
First we check to see if the path even matches, failing that it’s obvious that there isn’t a match. They we attempt to get a reference to the desired assembly. Of course if that fails then there’s no way to be able to serve files from it. Lastly we check the manifest for resources and if there are any does it contain the file we’re looking for. A file name mangling needs to occur (in ConstructAssemblyResourceName) because of the way the files are named as resources.
There are a couple of helper methods used in the above block, they are just there to keep things neat.
private String ConstructAssemblyResourceName(string resourcePath)
{
// nix the base path
String resourceName = resourcePath.Remove(0, VirtualPath.Length);
// tack on the base namespace
if (VirtualFileSystemBaseNamespace.Length > 0)
{
resourceName = VirtualFileSystemBaseNamespace + '/' + resourceName;
}
// replace directory seperators with .'s
resourceName = resourceName.Replace('/', '.');
return resourceName;
}
private Assembly GetAssemblyReference()
{
if (assemblyReference != null)
return assemblyReference;
String binDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
String assemblyName = Path.Combine(binDir, VirtualFileSystemAssembly);
Assembly assembly;
try
{
assembly = Assembly.LoadFile(assemblyName);
}
catch
{
return null;
}
// if it is a real assembly - keep it
if (assembly != null)
assemblyReference = assembly;
return assembly;
}
Download the source code: Legomaster.AssemblyPathProvider.
{ 1 } Trackback
[...] we previously discussed being able to access data directly from an assembly to build the views. The VirtualPathProvider provides what we need. Though first after more testing a better way to handle file access came [...]