Programming Microsoft ASP.NET 4 - Dino Esposito [70]
}
public class PictureViewerHandler : IHttpHandler
{
// Override the ProcessRequest method
public void ProcessRequest(HttpContext context)
{
PictureViewerInfo info = GetFolderInfo(context);
string html = CreateOutput(info);
// Output the data
context.Response.Write("
context.Response.Write("Picture Web Viewer");
context.Response.Write("
context.Response.Write(html);
context.Response.Write("");
}
// Override the IsReusable property
public bool IsReusable
{
get { return true; }
}
...
}
Retrieving the actual path of the folder is as easy as stripping off the folder.axd string from the URL and trimming any trailing slashes or backslashes. Next, the URL of the folder is mapped to a server path and processed using the .NET Framework API for files and folders to retrieve all image files:
private static IList { String[] fileTypes = { "*.bmp", "*.gif", "*.jpg", "*.png" }; var images = new List foreach (var files in fileTypes.Select(di.GetFiles).Where(files => files.Length > 0)) { images.AddRange(files); } return images; } The DirectoryInfo class provides some helper functions on the specified directory; for example, the GetFiles method selects all the files that match the given pattern. Each file is wrapped by a FileInfo object. The method GetFiles doesn’t support multiple search patterns; to search for various file types, you need to iterate for each type and accumulate results in an array list or equivalent data structure. After you get all the images in the folder, you move on to building the output for the request. The output is a table with a fixed number of cells and a variable number of rows to accommodate all selected images. For each image file, a new private static String CreateOutputForFolder(PictureViewerInfo info, DirectoryInfo di) { var images = GetAllImages(di); var t = new Table(); var index = 0; var moreImages = true; while (moreImages) { var row = new TableRow(); t.Rows.Add(row); for (var i = 0; i < info.ColumnCount; i++) { var cell = new TableCell(); row.Cells.Add(cell); var img = new Image(); var fi = images[index]; img.ImageUrl = fi.Name; img.Width = Unit.Pixel(info.DisplayWidth); var a = new HtmlAnchor {HRef = fi.Name}; a.Controls.Add(img); cell.Controls.Add(a); index++; moreImages = (index < images.Count); if (!moreImages) break; } } } You might want to make the handler accept some optional query string parameters, such as the width of images and the column count. These values are packed in an instance of the helper class PictureViewerInfo along with the name of the folder to view. Here’s the code to process the query string of the URL to extract parameters if any are present: var info = new PictureViewerInfo(); var p1 = context.Request.Params["Width"]; var p2 = context.Request.Params["Cols"]; if (p1 != null) info.DisplayWidth = p1.ToInt32(); if (p2 != null) info.ColumnCount = p2.ToInt32(); ToInt32 is a helper extension method that attempts to convert a numeric string to the corresponding integer. I find this method quite useful and a great enhancer of code readability. Here’s the code: public static Int32 ToInt32(this String helper, Int32 defaultValue = Int32.MinValue) { Int32 number; var result = Int32.TryParse(helper, out number); return result ? number : defaultValue; } Figure 4-4 shows the handler in action. Figure 4-4. The picture viewer handler in action with a given number of columns and a specified width. Registering the handler is easy too. You just add the following script to the tag is created through the Image control. The width attribute of this file is set to a fixed value (say, 200 pixels), causing browsers to automatically resize the image. Furthermore, the image is wrapped by an anchor that links to the same image URL. As a result, when the user clicks on an image, the page refreshes and shows the same image at its natural size.