I have a WebForms application running on IIS Express.
I'm using directoryBrowse=enabled
to let users access parts of the file structure in order to download and open files.
When I access a public directory on the website, a standard IIS directory listing page is displayed with the directory contents as usual.
I would like to register a custom handler specifically for directory browsing to control what is displayed and how when browsing directories. I know how to register a handler for a specific file or file type, however I don't know how to register a handler for a directory (ideally the same handler for any directory globally).
I have found an answer myself. Posting for any finders with similar questions.
It turns out that I can register a handler for path */
:
<add name="directory-handler" type="DirectoryHandler" path="*/" verb="*"/>
The server will then use this handler for any request ending with '/', except existing pages through FriendlyUrls or valid configured routes, which means it will use this handler for any directories in the server file tree. Then I create a new IHttpHandler called DirectoryHandler:
public class DirectoryHandler : IHttpHandler
{
public const string DirectoryBrowserPage = "/Browse/";
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context)
{
context.Response.Redirect(DirectoryBrowserPage + context.Request.Path);
}
}
This will redirect any requests pointing to a directory to mypage.com/Browse/[Request.Path]
Then, I register a new route in RouteConfig.cs
:
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
//Conflicting routes must be defined before friendlyurls are
routes.Add("Browse", new Route("Browse/{*path}", new GenericRouteHandler("~/Browse.aspx")));
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings);
}
}
Implement GenericRouteHandler
:
public class GenericRouteHandler : IRouteHandler
{
public GenericRouteHandler(string virtualPath)
{
this.VirtualPath = virtualPath;
}
public string VirtualPath { get; private set; }
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var page = BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(Page)) as IHttpHandler;
foreach (var urlParm in requestContext.RouteData.Values)
{
requestContext.HttpContext.Items[urlParm.Key] = urlParm.Value;
}
return page;
}
}
Finally, I create the Browse page itself, where I can access the requested directory path via:
string path = HttpContext.Current.Items["path"] as string;
The rest is then just a matter of manually creating the views, permissions and behavior in the Browse page.