Search - Articles - Dev Forums - Favorites - Member Login  
DevASP.NET for ASP.NET, VB.NET, XML and C# (C-Sharp) Developers Tuesday, March 16, 2010

Dev Articles
Search Directory
ASP.NET
VB.Net
C-Sharp
SQL Server
 


The File Manager's Main Page


Before starting to write the code for this page, which is quite long, let's see how the page will look when it is finished. The screenshot below shows the main page of the finished FileManager while it is browsing the content of the ThePhile web directory:

 


The page lists the directories first and then the files. Clicking the name of an item navigates to that subdirectory or file. For each item the page shows quite a lot of information, aligned by several columns, and some image buttons that allow us to rename the item, edit its attributes, edit a file's content, or download a file. The screenshot describes all the links so you should have no problems understanding how this interface works.

 

We can now start writing the page that will actually allow the administrator to navigate the site. We'll develop it piece by piece, starting from a simple explorer that just shows the directories and files, and progressively adding more and more information and commands.

 

First of all, create a new web form called BrowseFiles.aspx, and add the following code:

 

<%@ Page language="c#" Codebehind="BrowseFiles.aspx.cs"

    AutoEventWireup="false"

    Inherits="Wrox.WebModules.FileManager.Web.BrowseFiles" %>

<%@ Register TagPrefix="FileManager" TagName="Footer" src="Footer.ascx" %>

<%@ Register TagPrefix="FileManager" TagName="Header" src="Header.ascx" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html>

  <head>

    <title>FileManager: Browse Files</title>

    <link rel="stylesheet" href="/ThePhile/Styles/ThePhile.css"

        type="text/css">

    <meta name="CODE_LANGUAGE" Content="C#">

  </head>

  <body>

    <form id="BrowseFiles" method="post" runat="server">

      <FileManager:Header ID="Title" runat="server" />

      <br>

      <asp:Table runat="server"

          CssClass="Grid_Header_Thin" Width="100%">

        <asp:TableRow>

          <asp:TableCell Width="36">

            <asp:Image runat="server" Height="32" Width="32"

                ImageUrl="./Images/OpenFolder.gif" />

          </asp:TableCell>

          <asp:TableCell>

            <asp:Label runat="server" ID="FolderDescription"/>

          </asp:TableCell>

        </asp:TableRow>

      </asp:Table>

          

      <asp:Table ID="FoldersAndFiles" runat="server"

          CssClass="Grid_General" Width="100%">

        <asp:TableRow CssClass="Grid_Header">

          <asp:TableCell Text="Index" />

        </asp:TableRow>

      </asp:Table>

 

      <br>

      <asp:Label ID="StatusMessage" runat="server"

          CssClass="StatusMessage" Visible="False" Width="100%" />

      <asp:Label ID="FolderStyle" runat="Server"

          Text="Grid_Item" Visible="false" />

      <asp:Label ID="FileStyle" runat="Server"

          Text="Grid_AlternatingItem" Visible="false" />

    </form>

    <FileManager:Footer ID="Footer" runat="server" />

  </body>

</html>


At this point the page does not contain many controls. We'll add others along the way, but it's worth describing each of them briefly here:

 

q        The table at the top of the page has two columns. The first one shows an icon representing an open folder, while the cell on the right has a label that will be set dynamically to show the virtual and physical path of the folder whose content is currently listed on the page.

q        The second table, named FoldersAndFiles, is the table where we'll actually show the current folder's subdirectories and files. At this point it has just one column for the item name (file or directory). Later in the chapter we'll add more columns for item attributes and command buttons.

q        The StatusMessage label is used to display text representing errors and exceptions.

q        The FileStyle and FolderStyle controls are two invisible labels. They are only used to store the name of the style for the rows that will be dynamically created from the code-behind class, to display files or folders respectively. Instead of hard coding such settings in the compiled assembly, we want to leave them in the ASPX page (which can be easily modified without the need to recompile anything) and retrieve them later in the code-behind.

Listing the Contents of a Folder

It's time to write the code that shows the contents of the selected folder in the table. Most of the following code-behind code, BrowseFile.aspx.cs, is auto-generated by VS.NET. The procedure we need to focus on is Page_Load.

 

The virtual path of the folder to scan is passed along with the page URL, as a parameter called Folder. If not specified, the website root is taken as the default. The procedure gets the parameter value, stores it in a private variable, folderPath, and shows the virtual and physical path in the description table at the top of the page.

 

A second routine, called FillFoldersAndFilesTable, is then executed, and that is the one that finally scans the folder. Even though at this point the result just shows the folder and file names, with no additional information, the code for FillFoldersAndFilesTable is quite long, so we've left it out for the time being. Here is the remainder of the class:

 

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Web;

using System.Web.SessionState;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.IO;

 

namespace Wrox.WebModules.FileManager.Web

{

  public class BrowseFiles : System.Web.UI.Page

  {

    protected System.Web.UI.WebControls.Table FoldersAndFiles;


    protected System.Web.UI.WebControls.Label FolderDescription;

    protected System.Web.UI.WebControls.Label FolderStyle;

    protected System.Web.UI.WebControls.Label FileStyle;

 

    protected System.Web.UI.WebControls.Label StatusMessage;

    protected System.Web.UI.WebControls.Table Table1;

 

    private string folderPath;

       

    private void Page_Load(object sender, EventArgs e)

    {

      // extract from the querystring the path to scan

      folderPath = Request.Params["Folder"];

      if (folderPath == null || folderPath=="/")

        folderPath = Request.ApplicationPath.ToString();

      // if the folder is not "/" but it ends with "/", remove the last /

      else if (folderPath.EndsWith("/"))     

        folderPath = folderPath.Substring(0, folderPath.Length-1);

 

      // write the physical and virtual path

      FolderDescription.Text = "Virtual folder: " + folderPath +

          "<br>Physical folder: " + Server.MapPath(folderPath);

      // actually scan the specified folder

      FillFoldersAndFilesTable();

    }

       

    private void FillFoldersAndFilesTable()

    {

      //to be added next...

    }

 

    public BrowseFiles()

    {

      Page.Init += new System.EventHandler(Page_Init);

    }

 

    private void Page_Init(object sender, EventArgs e)

    {

      InitializeComponent();

    }

       

    private void InitializeComponent()

    {   

      this.Load += new System.EventHandler(this.Page_Load);

    }

  }

}


Let's now fill in the code for the FillFoldersAndFilesTable procedure, one part at a time. It begins by retrieving the collection of child files and sub directories for the folder stored in the private folderPath variable:

 

private void FillFoldersAndFilesTable()

{

  string location;

 

  DirectoryInfo parentDir;

  DirectoryInfo[] childDirs;

  FileInfo[] childFiles;

  try

  {

    parentDir = new DirectoryInfo(Server.MapPath(folderPath));

    // get all the child directories and files

    childDirs = parentDir.GetDirectories();

    childFiles = parentDir.GetFiles();

  }

  catch (Exception exc)

  {

    StatusMessage.Text = exc.Message;

    StatusMessage.Visible = true;

    return;

  }

 

The code is protected within a trycatch block, so in cases where the folderPath folder does not exist an error message is shown and the procedure exits gracefully.

 

Next, the procedure checks whether the current folder is the site root. If it is not, the first row in the table must be a link to the parent folder, whose path is retrieved by removing the part after the last "/" character (remember that we're working with a virtual path here, so we cannot use Directory.GetParent as we would do with a physical path):

 

  TableRow rowItem;

  TableCell cellItemLink;

  HyperLink linkItem;

 

  Style styleFolderRow = new Style();

  styleFolderRow.CssClass = FolderStyle.Text;

  Style styleFileRow = new Style();

  styleFileRow.CssClass = FileStyle.Text;

  Style styleLink = new Style();

  styleLink.CssClass = "GridLink";

 

  // if the current folder is not the root, add the FolderUp icon and link

  if (folderPath != "/")

  {

    rowItem = new TableRow();

    cellItemLink = new TableCell();

    linkItem = new HyperLink();

             

    // add the link that points to the parent directory

    linkItem.Text = " ...";


    int lastSlashIndex = folderPath.LastIndexOf("/");

    location = folderPath.Substring(0,lastSlashIndex);

    if (location.Length==0) location="/";

    linkItem.NavigateUrl = "BrowseFiles.aspx?Folder=" + location;

    linkItem.ApplyStyle(styleLink);

    cellItemLink.Controls.Add(linkItem);

 

    // add the cell to the new row

    rowItem.Cells.Add(cellItemLink);

      

    // add the row to the table

    rowItem.ApplyStyle(styleFolderRow);

    FoldersAndFiles.Rows.Add(rowItem);

  }

 

Now we cycle through the childDirs collection and add the name of all the child directories. The name text links to BrowseFiles.aspx, with the Folder parameter set to the folderPath plus the name of the childDirs collection's current folder:

 

  // add all the child directories first

  foreach (DirectoryInfo childDir in childDirs)

  {

 

    // create the required cells and controls

    rowItem = new TableRow();

    cellItemLink = new TableCell();

    linkItem = new HyperLink();

             

    // create the link that points to this sub-directory

    linkItem.Text = childDir.Name;

    location = folderPath;

    if (location.EndsWith("/"))

      location += childDir.Name;

    else

      location += "/" + childDir.Name;

    linkItem.NavigateUrl = "BrowseFiles.aspx?Folder=" + location;

    linkItem.ApplyStyle(styleLink);

    cellItemLink.Controls.Add(linkItem);           

 

    // add the cell to the new row

    rowItem.Cells.Add(cellItemLink);

       

    // add the new row to the table

    rowItem.ApplyStyle(styleFolderRow);

    FoldersAndFiles.Rows.Add(rowItem);

  }

 

Note that, as for the previous piece of code, the dynamically created cell is added to a new row, which is added to the table's Rows collection.


The code that cycles through the collection of child files is very similar to the code just shown, except that the link behind the name of each file opens a new window to display the file (letting the web browser select how to display it):

 

  // now add each child file

  foreach (FileInfo childFile in childFiles)

  {

 

    // create the required cells and controls

    rowItem = new TableRow();

    cellItemLink = new TableCell();

    linkItem = new HyperLink();

    int extIndex;

       

    // create and add the link that points to this file in a new window

    linkItem.Text = childFile.Name;

    location = folderPath;

    if (location.EndsWith("/"))

      location += childFile.Name;

    else

      location += "/" + childFile.Name;

    linkItem.NavigateUrl = location;

    linkItem.Target = "_blank";

    linkItem.ApplyStyle(styleLink);

    cellItemLink.Controls.Add(linkItem);

 

    // add the cell to the new row

    rowItem.Cells.Add(cellItemLink);

 

    // add the new row to the table

    rowItem.ApplyStyle(styleFileRow);

    FoldersAndFiles.Rows.Add(rowItem);

  }

}

 

The code that allows the basic navigation functionality is now complete, and we can finally compile the assembly and run the page. If you set BrowseFiles.aspx as the Start Page (right click on the file in the Solution Explorer and click the respective command) the project is automatically compiled and the page is run when you press F5. Otherwise open Internet Explorer and navigate to http://localhost/ThePhile/Modules/FileManager/BrowseFiles.aspx.


The screenshot below represents what you should see if you use the file manager to navigate to the ThePhile folder:

 


DevASP.Net - Disclaimer - Privacy
© 2002-2010 DevASP.net