Archive

Archive for the ‘ASP.NET’ Category

VirtualPathProvider for Assemblies

May 2nd, 2009 Comments off

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.

Categories: ASP.NET Tags: ,