Asynchronous TreeView in ASP.NET MVC

Today I'm going to show how to create a completely asynchronous TreeView in ASP.NET MVC. To achieve this I will use jQuery TreeView plugin from bassistance.de. General purpose of this plugin is converting unordered list into an expandable and collapsible tree. I'm not going to write about converting static list, because that is really straightforward. I will focus on asynchronous features of this plugin.
We will start by referencing necessary files:
<head>
  <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
  <link href="../../Content/jquery.treeview.css" rel="stylesheet" type="text/css" />
  <script src="/Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
  <script src="/Scripts/jquery.treeview.min.js" type="text/javascript"></script>
  <script src="/Scripts/jquery.treeview.async.js" type="text/javascript"></script>
</head>

Now we need to add placeholder (an empty unordered list) for TreeView:
<ul id="trFileBrowser"></ul>
After that we can write initialization javascript:
<script type="text/javascript">
  $(document).ready(function() {
    $('#trFileBrowser').treeview({
      url: '/Home/FileBrowserData/'
    })
  });
</script>

Let's move on to controller action. TreeView makes a GET request with one parameter: root.
public ActionResult FileBrowserData(string root)
{
}

If the request comes from empty TreeView root has a constant value 'source', otherwise it contains id of expanding node:
public ActionResult FileBrowserData(string root)
{
  DirectoryInfo rootDirectory = null;
  if (root == "source")
    rootDirectory = new DirectoryInfo(@"D:\Books\");
  else
    rootDirectory = new DirectoryInfo(root);
  var directoryChildren = from child in rootDirectory.GetFileSystemInfos()
                          orderby child is DirectoryInfo descending
                          select child;
}

In the response we should return an array of objects representing TreeView nodes. I have prepared a TreeViewNode class (it serves better for presentation purposes) but you are free to use an anonymous type with only those properties which you need (basically only the text property is required):
/// <summary>
/// jQuery TreeView plugin node
/// </summary>
public class TreeViewNode
{
  ...

  #region Properties
  /// <summary>
  /// Node identifier
  /// </summary>
  public string id
  {
    ...
  }

  /// <summary>
  /// Node text
  /// </summary>
  public string text
  {
    ...
  }

  /// <summary>
  /// Whether node is expanded
  /// </summary>
  public bool expanded
  {
    ...
  }

  /// <summary>
  /// Whether node has children
  /// </summary>
  public bool hasChildren
  {
    ...
  }

  /// <summary>
  /// CSS classes for node
  /// </summary>
  public string classes
  {
    ...
  }

  /// <summary>
  /// Node children's
  /// </summary>
  public TreeViewNode[] children
  {
    ...
  }
  #endregion
}

We can finish our controller action:
public ActionResult FileBrowserData(string root)
{
  DirectoryInfo rootDirectory = null;
  if (root == "source")
    rootDirectory = new DirectoryInfo(@"D:\Books\");
  else
    rootDirectory = new DirectoryInfo(root);
  var directoryChildren = from child in rootDirectory.GetFileSystemInfos()
                          orderby child is DirectoryInfo descending
                          select child;

  List nodes = new List();
  foreach (FileSystemInfo directoryChild in directoryChildren)
  {
    bool isDirectory = directoryChild is DirectoryInfo;
    nodes.Add(new TreeViewNode() {
      id = directoryChild.FullName,
      text = directoryChild.Name,
      classes = isDirectory ? "folder" : "file",
      hasChildren = isDirectory
    });
  }

  return Json(nodes.ToArray());
}

Once again you can take a look at my Books directory:

Source code can be downloaded here