When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, September 1, 2010

Displaying Files and Folders in a GridView

By Scott Mitchell


Introduction


The .NET Framework provides a variety of classes in the System.IO namespace that simplify working with the file system. Using these classes it's possible to delete files and folders, to create new files, to edit existing files, and more. These classes, combined with ASP.NET's suite of Web controls and databinding syntax, make it quite easy to present information about the files on the web server's file system to visitors to your website. With a bit of markup and code, it's possible to add a simple file browser to a web page that allows users to view the files and folders from a particular directory on the web server. Such file browsers are useful if you let users upload content to the website and need to let them view their uploaded content. If you have a folder that contains user-accessible content like images, PDF files and Word documents, a file browser offers a quick and easy way for users to see what content is available and to view content of interest.

Back in 2003 I wrote an article titled Displaying the Files in a Directory using a DataGrid that showed how to list the files of a particular folder in a DataGrid Web control. This dated article still attracts a decent amount of traffic and questions from readers, so much so that I thought it worthwhile to update the content to use the latest technology, namely ASP.NET 4 and the GridView Web control. I also added some new features. For example, the file browser now lists both files and folders, allowing users to view the files in subfolders. Also, I moved the markup and code into a User Control, which simplifies adding the file browser to an ASP.NET page. This article walks through this new, updated version; the complete, working code is available for download at the end of this article. Read on to learn more!

- continued -

The file browser.

First Things First: A Quick Overview of the File Browser


Before we get started with examining the guts of the new file browser, let's take a moment to discuss what it is we're trying to accomplish. An online file browser is a user interface on a web page through which the visitor can explore the contents of a particular directory on the web server's file system. The directory of interest can be a directory within the web application or a directory outside of the web root. For instance, if the web server is rooted at the folder C:\Sites\MySite, the file browser could be used to display the contents in a particular folder within the web application, such as C:\Sites\MySite\Content, or it could be used to display the contents of a folder outside of the web application's "space", such as D:\Reports.

The screen shot to the right shows what the file browser I've created looks like when pointed to a directory with three folders named For Jisun, Images, and Old, and a number of files, including 010401-1.txt, f1040ez.pdf, and Flowers.jpg, among others. Much like Windows Explorer, the grid displays the name of each file and folder, its type, the date modified, and (for files) its size.

Clicking on a folder causes a postback. On postback, the grid is repopulated with the contents of the selected folder's files and subfolders. When using the file browser to view the contents of a folder outside of the web application root the files are listed as text. When the file browser points to a folder within the web application then the file names are displayed as hyperlinks to the actual file. For example, if the grid to the right was configured to display the contents in the ~/Content folder then clicking the f1040ez.pdf file in the grid to the right would send the user to www.yoursite.com/Content/f1040ez.pdf, which would display the PDF file in the user's browser.

Adding the File Browser to an Existing Web Page


The file browser I created is implemented as a User Control, which simplifies adding the file browser to an ASP.NET page. To add the file browser to a page on your website, start by downloading the complete code at the end of this article. The download includes the User Control in both VB and C#, along with a working demo. I encourage you to try out the demo and get familiar with the User Control's usage and functionality before attempting to add it to your website.

Once you are ready to add the User Control to your website, copy the appropriate code and markup files from the sample application's ~/UserControls folder to your web application. (Specifically, if your application is in C# then copy the FileGridCS.ascx and FileGridCS.ascx.cs files; if you use Visual Basic, copy the FileGridVB.ascx and FileGridVB.ascx.vb files.) Also copy the ~/Images/folder.png image from the sample application to the ~/Images folder in your application, as this image is used by the User Control to show the folder icon next to folder names. Finally, you'll need to include the FileSystemItem class in your project, which is defined in a class file in the App_Code folder. If you are using a Web Site Project, you can simply copy the C# or VB file into your application's App_Code folder. If you are using a Web Application Project, add the appropriate class file to your project in any folder (such as a folder named Classes), but for reasons that are beyond the scope of this article, do not name that folder App_Code.

Now, open the ASP.NET page that is to include the file browser and go to the Design view. Then, from the Solution Explorer, drag the User Control onto the Design surface. Doing this adds two bits of markup to your ASP.NET page:

  • A @Register directive that registers the User Control. This will similar to the following: <%@ Register src="UserControls/FileGridCS.ascx" tagname="FileGridVB" tagprefix="uc1" %>
  • The markup for the User Control, which will look something like the following: <uc1:FileGridVB ID="FileGridCS1" runat="server" />
If you visit the ASP.NET page at this point you will get an exception that states, "The HomeFolder setting '' is not set or is invalid." For the file browser to display folder and file information you must specify the path to the directory whose folders and files you want to display. This information is specified via the User Control's HomeFolder property. If this directory is a folder within the web application then specify the directory using the tilde character (~) like so: ~/DirectoryName. If this directory is outside of the web application then specify the directory name using the fully qualified path, like so: D:\Public\Report Files.

By default, the file browser displays all of the folders and files in the specified directory on the screen. If you want to only display a certain number of folders and files at a time then set the User Control's PageSize property to the number of folders or files to show per page. (The grid in the screen shot above has its PageSize property set to 10.) After setting the HomeFolder property and (optionally) the PageSize property, your User Control's markup should look similar to the following:

<uc1:FileGridVB ID="FileGridVB1" runat="server" HomeFolder="~/Content" PageSize="10" />

After setting (at minimum) the HomeFolder property, take a moment to view your ASP.NET page. At this point you should see a grid that lists the folders (if any) and files in the specified directory. If the directory is a folder within the web application then the files should be clickable, and clicking a file should display it in the browser. Clicking on a folder name triggers a postback and on refresh the contents of that folder are displayed. The screen shot below shows the file browser after clicking the folder name Old - this lists the files and folders in the ~/Content/Old folder. Note the folder named ... When clicked, the .. folder returns the visitor to the parent directory. Also note that the listing in the screen shot below includes an additional folder, For Alice; clicking that folder name would display the contents of the ~/Contents/Old/For Alice folder.

The file browser lists the contents of the Old subfolder.

At this point we've covered how to add the file browser to an existing ASP.NET page, but we've yet to explore how the User Control works behind the scenes. The remainder of this article examines some of the more interesting and educational aspects of the file browser control and is worth reading if you plan on extending or enhancing the file browser User Control or if you just want to learn more about how to work with the file system in an ASP.NET application.

Getting Information About the Files and Folders in a Specified Directory


The file browser User Control uses the DirectoryInfo class to retrieve the list of files and folders in the folder of interest. To use the DirectoryInfo class we start by specifying the path to the directory whose information we are interested in. The User Control has a property, CurrentFolder, that returns the path to the folder whose items are to be displayed. Initially, the User Control's CurrentFolder property is equal to its HomeFolder property, but the CurrentFolder property is reassigned if the user clicks on a folder name (more on that later).

The GridView is populated programmatically whenever the PopulateGrid method is called. Let's delve into this method's code... (Note: I've left out some of the code in the PopulateGrid method to focus on the more germane parts.)

private void PopulateGrid()
{    // Get the list of files & folders in the CurrentFolder
   var currentDirInfo = new DirectoryInfo(this.CurrentFolder);

Once we have a DirectoryInfo object, we can use the GetDirectories and GetFiles methods to get information about the directory's subfolders and files. The GetDirectories method returns an array of DirectoryInfo objects; the GetFiles method returns an array of FileInfo objects. The DirectoryInfo and FileInfo classes have properties that provide information about each folder or file, including the name of the file/folder, the last access date, the creation date, and so on.

   var folders = currentDirInfo.GetDirectories();
   var files = currentDirInfo.GetFiles();

In order to show the set of subfolders and the set of files in a single GridView control we need to combine them into a common type. (You cannot bind heterogeneous types in a databound control.) To this end, I created a new class named FileSystemItem - well, actually, one named FileSystemItemCS and one named FileSystemItemVB, which are C# and VB versions, respectively. In a nutshell, the PopulateGrid method gets the folders and files in the requested directory and then loops through those, creating a FileSystemItem object for each folder and file. This collection of FileSystemItem objects is then what is bound to the GridView.

This FileSystemItem class has those properties I was interested in displaying in the file browser - Name, FullName, Size, CreationTime, and others - along with a FileSystemType read-only property that returns a friendly description based on the file's extension. (For example, for files with the extension .doc and .docx the FileSystemType property returns the string "Microsoft Word document.")

Here is the code that creates the list of FileSystemItem objects, loops through the DirectoryInfo and FileInfo arrays and adds them to the list of FileSystemItem objects, and then binds that list to the GridView.

   var fsItems = new List<FileSystemItemCS>();

   foreach(var folder in folders)
      fsItems.Add(new FileSystemItemCS(folder));

   foreach(var file in files)
      fsItems.Add(new FileSystemItemCS(file));

   gvFiles.DataSource = fsItems;
   gvFiles.DataBind();
}

Note that adding information about a file or folder to the fsItems list is done in one line of code, by calling new FileSystemItemCS(folder) or new FileSystemItemCS(file). As you may have surmised, the FileSystemItem class offers two constructors, one that accepts a DirectoryInfo object as input and another that accepts a FileInfo object. Both constructors assign the passed-in object's property values to the new FileSystemItem object's properties.

Drilling Into a Subfolder


Each subfolder is displayed in the GridView as a LinkButton whose CommandArgument property is assigned the name of the folder. When the LinkButton is clicked, a postback ensues and the GridView fires its RowCommand event. The User Control has a RowCommand event handler that updates the CurrentFolder property and then calls the PopulateGrid method, to display the folders and files of the new folder in the grid.

When drilling down into a subfolder, the code is very straightforward - we can use the Path.Combine method to combine the current folder path (CurrentFolder) with the name of the folder the user clicked (e.CommandArgument) and assign this value back to the CurrentFolder property.

protected void gvFiles_RowCommand(object sender, GridViewCommandEventArgs e)
{
   if (e.CommandName == "OpenFolder")
   {
      if (string.CompareOrdinal(e.CommandArgument.ToString(), "..") == 0)
         ...
      else
         this.CurrentFolder = Path.Combine(this.CurrentFolder, e.CommandArgument as string);

      PopulateGrid();
   }
}

We have to do a bit more work when going up a directory (that is, when clicking the .. folder, which is displayed when listing the contents of any folder other than the HomeFolder). Imagine that we are showing the contents of the folder ~/Content/Old/For Alice when the user asks to go up to the parent folder. To accomplish this we need to hack off the last folder name (For Alice), changing the CurrentFolder property from ~/Content/Old/For Alice to ~/Content/Old. This can be done with some deft string manipulation - namely, splitting the string on all directory delimiters and then piecing it back together but omitting the last part.

If you are not familiar with the string's Split and Join methods, understand that they break up a string into an array of strings and piece an array of strings back together into a single string, respectively. In the code below, the value of the CurrentFolder folder is broken up into an array of strings using the backslash character as a delimiter. That is, a directory of C:\MySites\Content\Old\For Alice would be split into an array with five items:

  • C:
  • MySites
  • Content
  • Old
  • For Alice
The Join method then says, "Put this array back into a string, but use only the first four elements in the array," resulting in a value of C:\MySites\Content\Old, which is what is assigned back to the CurrentFolder property.

var currentFullPath = this.CurrentFolder;

if (currentFullPath.EndsWith("\\") || currentFullPath.EndsWith("/"))
   currentFullPath = currentFullPath.Substring(0, currentFullPath.Length - 1);

currentFullPath = currentFullPath.Replace("/", "\\");

var folders = currentFullPath.Split("\\".ToCharArray());

this.CurrentFolder = string.Join("\\", folders, 0, folders.Length - 1);

Looking Forward...


The User Control presented in this article was designed to make it easy to add file browsing capabilities to an existing ASP.NET web page. As we discussed, the User Control can point to any folder on the web server's file system (either one in the web application's root or one outside it). There's also a User Control property to turn on and configure paging in the GridView (PageSize).

All that being said, there are still a number of enhancements that could be added to this User Control. It would be nice to be able to enable sorting, for instance. Also, it would be ideal if instead of displaying a selected file the page developer using the file browser User Control could indicate that a postback should occur instead, at which point she could determine what file was selected and decide what to do with that request. Likewise, it would be nice to enable the page developer to turn on the ability to delete files.

You are welcome to make any enhancements. If you do, please feel free to share them with me! I hope to add some of these enhancements myself over time, at which point I'll update this article accordingly.

Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the complete working code sample (includes VB and C# code)


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article