skip to Main Content

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).

2

Answers


  1. Chosen as BEST ANSWER

    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.


  2. Hum, would it not be better to turn off folder browsing, and then say offer your own UI that is web based?

    I note the above, since this VAST improves security, allows un-limited customizing of the UI. And say would allow limiting of folders and files based on the user’s logon.

    And better yet, you can also use folders OTHER then the server, but not have to create and map virtual folders from the web server to those other servers.

    This means, that for additional folders etc., you don’t have change the web server configuration.

    Say you drop in a tree view control to the web page.

    Chose the image set as "windows xp file explore".

    enter image description here

    So, now we have this markup:

    <asp:TreeView ID="TreeView1" runat="server" ImageSet="XPFileExplorer"
        NodeIndent="15" OnTreeNodeExpanded="TreeView1_TreeNodeExpanded1">
        <HoverNodeStyle Font-Underline="True" ForeColor="#6666AA" />
        <NodeStyle Font-Names="Tahoma" Font-Size="8pt" ForeColor="Black"
            HorizontalPadding="2px" NodeSpacing="0px" VerticalPadding="2px" />
        <ParentNodeStyle Font-Bold="False" />
        <SelectedNodeStyle BackColor="#B5B5B5" Font-Underline="False"
            HorizontalPadding="0px" VerticalPadding="0px" />
    </asp:TreeView>
    

    So, code behind to "browse" folders is not a lot of code, but you can of course introduce restrictions on file types, and base the folder (limits) on the user’s logon.
    So, say this code:
    (it is not even recursive, and recursion is not required).

    Dim sRoot As String = "c:SERVER01"
    
    Public Class MyFolder
        Public MyFiles As FileInfo()
        Public MyFolders As DirectoryInfo()
    End Class
    
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
        If Not IsPostBack Then
            lblFolder.Text = sRoot
            Dim MyFiles As MyFolder = GetFiles(sRoot)
            LoadTreeFiles(sRoot, MyFiles, "", Nothing)
        End If
    
    End Sub
    
    
    Public Function GetFiles(sRootFolder As String) As MyFolder
    
        Dim MyDir As New DirectoryInfo(sRootFolder)
        Dim cMyFolder As New MyFolder
    
        cMyFolder.MyFolders = MyDir.GetDirectories("*.*", SearchOption.TopDirectoryOnly)
        cMyFolder.MyFiles = MyDir.GetFiles("*.*", SearchOption.TopDirectoryOnly)
    
        Return cMyFolder
    
    End Function
    
    
    Sub LoadTreeFiles(fRootL As String,
                      lParent As MyFolder,
                      sParentID As String,
                      tTreeNode As TreeNode)
    
        ' add folders if any
        For Each sFolder As DirectoryInfo In lParent.MyFolders
            Dim child As New TreeNode
            child.Text = sFolder.Name
            child.Value = sFolder.FullName
            child.Expanded = False
            child.PopulateOnDemand = True
            child.ShowCheckBox = False
    
            If sParentID = "" Then
                TreeView1.Nodes.Add(child)
            Else
                tTreeNode.ChildNodes.Add(child)
            End If
        Next
        ' now any files
        For Each sFile As FileInfo In lParent.MyFiles
    
            Dim child As New TreeNode
            child.Text = sFile.Name
            child.Value = sFile.FullName
            child.Expanded = False
            child.ShowCheckBox = True
            child.PopulateOnDemand = False
    
            If sParentID = "" Then
                TreeView1.Nodes.Add(child)
            Else
                tTreeNode.ChildNodes.Add(child)
            End If
        Next
    
    End Sub
    
    Protected Sub TreeView1_TreeNodeExpanded1(sender As Object, e As TreeNodeEventArgs) Handles TreeView1.TreeNodeExpanded
    
        Dim child As TreeNode = e.Node
        Dim dtChild As MyFolder = GetFiles(child.Value)
    
        LoadTreeFiles(child.Value, dtChild, child.Text, child)
    
    End Sub
    

    So, now the web page shows:

    enter image description here

    So, it is not clear if you need/want a custom handler, but only that of building some kind of UI with say a tree view control, and building your own file browse system as per above. Since I only load each folder “on demand”, then the speed of above is very fast, and even for a system with a large and deep folder hierarchy.

    The above has check boxes for multiple file selecting, but you could have a click on a file download.
    And the above design allows you to add additional UI options such as "select all this folder" or whatever.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search