EPiServer products can use Virtual Path Providers (VPP) to serve static files to visitors. The reason for using VPPs is to allow EPiServer products programmatic control of what files to send as well as additional security checks. VPP is the mechanism that ASP.NET uses to load and compile content. For a brief introduction, see ASP.NET Compilation Overview at MSDN.
When ASP.NET gets a request to supply a file based on a virtual path it looks in the registered chain of providers and feeds the virtual path to the first provider in the chain.
It is up to the provider to interpret the path to determine if this is a file which belongs in the providers underlying file system. If so, it serves the file back to ASP.NET, otherwise it calls the next provider to give it a chance to serve the file and so on.
A provider can of course accept the virtual path as valid for the file system, but the file does not exist. In such case a null reference is returned, eventually turning up as an HTTP 404 response.
A file served from a provider must extend the abstract class of System.Web.Hosting.VirtualFile. For serving directories the base class is System.Web.Hosting.VirtualDirectory. The core API is as mentioned only intended for serving files but this behavior is extended in the EPiServer products.
In order for you to use the providers on all requests, not only those served by ASP.NET you can add a wildcard mapping in IIS to have ASP.NET serve for example image files etc. This will give your provider implementation to get requests for virtual paths, for example /EPiServerSample/upload/myImage.gif.
Virtual Paths Providers
When requesting instances using the HostingEnvironment you must provide a virtual path. This path is always relative to a URL. The EPiServer implementations of providers around the native file system and the versioning supports the ASP.NET standard of handling relative paths.
Examples of Virtual Paths (assuming the application root folder is http://localhost/EPiServerSample).
A virtual path cannot be relative to a host subfolder because the hosting environment cannot determine what it is relative to. This means it must be absolute from the host (as above) or resolved to absolute if in syntax of "~/". It also follows the URI syntax of an HTTP path, in other words forward slash, no query string etc.
A good recommendation for handling virtual paths is to use the class System.Web.VirtualPathUtility for converting between relative and absolute paths and for handling slashes.
There is a specific distinction between ~/upload and ~/upload/. The first refers to a file, the second to a directory.
Configuring a Virtual Path Provider
ASP.NET does not provide a configuration section in web.config for registering providers. This can only be done by API calls at runtime. EPiServer Framework has a configuration section which allows you to do this in the configuration file. The section is located under the XPath node /configuration/episerver.framework/virtualPathProviders.
The syntax for the provider configuration follows the same standard as membership and role providers. In fact it uses the same classes for reading the section from web.config. The registration of providers is done at application start-up.
Note that the order of the configured providers will matter. The provider at top will be instantiated first and added to the top of the provider chain. The next provider will also be added to the top of the chain pushing the previous down one step and so on.
Example of configuration from the /configuration/episerver.framework/virtualPathProviders section:
<virtualPathProviders> <add name="EPiServerUrlMappingVPP" type="EPiServer.Web.Hosting.VirtualPathMappedProvider, EPiServer.Framework"/> <add name="EPiServerNonUnifiedVPP" virtualPath="~/other/" physicalPath="C:\files\other" type="EPiServer.Web.Hosting.VirtualPathNonUnifiedProvider, EPiServer.Framework"/> </virtualPathProviders>
|name||Unique name of provider instance.|
|type||Type and Assembly information for instance creation using reflection API.|
|*||Implementation specific. Can be any name and arbitrary in number.|
VirtualPathNonUnifiedProvider implementation specific:
|virtualPath||Virtual path to file system root.|
|physicalPath||The filesystem path to use as the root. If Physical path has no value then it points to a directory with virtual path provider name under base path*. You can also rebase a PhysicalPath if it starts with [appDataPath] (e.g. [appDataPath]\Folder1) which means the value of physical path is rebased from basePath*.
*You can find the basePath in the episerver framewotk section in the episerver framework config file.
VirtualPathMappedProvider implementation specific:
Uses the /configuration/episerver.framework/virtualPathMappings section to map paths.
IIS Location Settings
The following is an example on how to configure the static file handler in IIS7.
<location path="Upload"> <staticFile expirationTime="-1.0:0:0"/> <system.webServer> <handlers> <add name="wildcard" path="*" verb="*" type="EPiServer.Web.StaticFileHandler, EPiServer.Framework"/> </handlers> </system.webServer> </location>