Some Techniques for Better Managing Files in Visual Studio 2005 Web Projects
Product Unit Manager, Web.NET
Microsoft Visual Studio 2005
Microsoft ASP.NET 2.0
Summary: Scott Guthrie looks at some techniques for managing large numbers of files and directories when creating Web projects in Microsoft Visual Studio 2005. (10 printed pages)
Note This article originally appeared on Scott's blog. Join in the discussion here.
Scenario #1: How to Manage a 5,000-Item /images Directory in a Web Project
Scenario #2: How to Dynamically Generate and Handle Temp Files in a Web Project
Scenario #3: How to Store Non-Deployed Files in Web Projects
I've seen several questions regarding techniques for structuring project layouts with Web projects in Microsoft Visual Studio 2005. In particular, I've received several good questions asking for ways to manage large image directories as well as temporary storage directories underneath Web project roots. One goal with both types of questions has been to find ways to prevent these files from showing up in the Visual Studio Web project solution explorer and cluttering up the Web project view, as well as to avoid being prompted to add these files/directories to source control during check-in. (Although you can just clear the option to have these files added to source control, having to do so can be a pain.)
This article covers some techniques for handling scenarios like these. Prior to reading further, I'd strongly recommend that you read my previous article on managing IIS Web projects with Visual Studio 2005: Using IIS with VS 2005 and the New Web Project System. The section on virtual directory mappings and how they are treated will be particularly pertinent to some of the techniques below.
Note that the final release of Visual Studio 2005 will have "Exclude File from Build" support, to allow you to exclude/include code from being part of a build or publishing operation. The techniques in this article are about going one step deeper, and having files disappear entirely from the solution explorer. This article will also discuss techniques for sharing common directories across multiple projects.
A really good scenario that someone sent my way today was one in which they currently have an e-commerce solution that has a 5,000-item product catalog. As part of their solution, they have an images subdirectory underneath their Web root that stores an image for each of the 5,000 products on disk.
They are worried about having two problems when they open up their Web project using Visual Studio 2005:
- They will have a 5,000-picture subdirectory in their heavily developed Web project, which will add clutter and slow down open/copy operations.
- Managing this directory with source control will be a real pain: When you check in, or check out of, Visual Source Safe it will verify that these files haven't changed or that they have been added to source control, which can really take a while. Ideally, there would be some way to manage these image files elsewhere.
A Technique to Make This Experience Much Better
For scenarios like this, involving directory resources, one technique that you can easily use to better manage these items in Web projects is to mark these directories as "virtual directories" in IIS. This does not require any code-changes—it is purely a configuration setting that you can manage using IIS.
Making These Directories "Virtual Directories" Provides Four Big Benefits
Benefit #1: Subdirectories marked as "virtual directories" in IIS will automatically be excluded from showing up in a Visual Studio 2005 Web project. A marker node will still remain in the solution tree, to indicate that a virtual subdirectory is present, but no files or subdirectories will be added; furthermore, the virtual directory and all of its contents will be excluded from all source control operations and publish deployment operations.
For example, Figure 1 shows the Web project, with the images subdirectory marked as a normal directory.
Figure 1. Large images directory
Figure 2 shows the same Web project, with the images subdirectory marked as a "virtual directory" in IIS. Note that, although there is still an images node in the hierarchy, to denote the presence of a virtual sub-directory, no content is included underneath it.
Figure 2. Marking the images directory as a virtual directory
Note that the content of the virtual directory will be automatically excluded from all deployment operations, and will not be included in the source control for the Web project (even in cases where the images virtual directory is physically stored underneath the Web project on disk).
Benefit #2: You can now store these directories anywhere on disk. If you want, you can continue to store them physically underneath the same Web app or site directory. You can also, optionally, store them elsewhere on disk. This can make some deployment scenarios much easier, since you can now manage these directory trees separately, and update and deploy their roots independently. Note that virtual directory views within the solution explorer will be the same, regardless of whether the physical images subdirectory is under the project directory or stored elsewhere—it is completely transparent to the active project.
Benefit #3: You can have multiple Web projects share the same virtual directories. This can be a very useful and powerful technique when you have shared images, CSS, or script libraries that you want to re-use across multiple Web sites or Web applications (for example, www.site1.com, www.site2.com, www.site3.com, and so on). One of the cool new features in the Visual Studio 2005 WYSIWYG designer is that it will follow virtual directory paths and load images, CSS files, and scripts correctly, even when they are stored in virtual directories.
For example, consider a scenario where you are building three different sites or applications, and you want them to share a common CSS design, and common corporate logo images. You could lay out your application structure as follows if you wanted to.
You could then map a virtual directory underneath each site, to point to the CommonVDir shared library directory. Not only will this work at runtime, but when you create a new page underneath the www.site1.com Web project and reference the commonvdir/css/style.css stylesheet, the Visual Studio 2005 Web designer will automatically pick up the styles and show things correctly in design view, even though the actual stylesheet is never checked in or managed in the www.site1.com Web project.
When you update a single CSS stylesheet under the c:\CommonVDir\CSS directory, the updates will immediately show in all three of the sites—both at runtime and design-time.
Benefit #4: You can optionally create additional Web projects to manage your various virtual directories. This allows you to manage these separate virtual folders using their own development/design team, Web project, and source control settings. For example, Figure 3 shows one solution in which not only the Web application is open, but so are a second and third Web project, to manage the images and styles virtual directories as separate isolated projects (which could be checked in separately under source control).
Figure 3. Working with images virtual directory
Another scenario that a few people have asked about is one in which they are dynamically generating XML files underneath their Web project at runtime, and they want to avoid having these files appear in their solution explorer and source control, and they also want avoid having them be deployed by Visual Studio's Publish Web feature.
A Technique to Make This Experience Much Better
For temporary file storage that is dynamically generated underneath a Web project or Web root, you might want to consider using hidden folders.
There Are Two Benefits to This Approach
Benefit #1: Hidden files and folders are automatically excluded from the Web project view under solution explorer, and they will be excluded from all source control operations.
For example, Figure 4 shows a Web project with a tempstorage directory that contains XML files.
Figure 4. Temporary storage directory
Figure 5 shows the same Web project, except that the tempstorage directory has now been marked with a "hidden" bit.
Figure 5. Temporary storage directory hidden
Benefit #2: IIS will, by default, block requests for content that is stored in hidden folders. This can be a useful security check, to help prevent temporary files from accidentally being downloaded by unauthorized users.
The following two lines of sample code demonstrate how to dynamically create a new temporary directory, and then mark it as hidden by using the System.IO namespace.
Directory.CreateDirectory("tempstorage"); File.SetAttributes("tempstorage", FileAttributes.Hidden);
Obviously, you can also just create the folder on the file system yourself, using Windows explorer, and then pull up its Properties dialog box and click the Hidden check box.
Note that whether a folder is hidden or not will not change any code or logic when accessing/writing files underneath it.
Important Note: For maximum security, I would always recommend that you not grant any write access to the directory underneath a Web project or application root. If you need to store temporary files somewhere, it is far more secure to store them in a totally non-accessible location. I've only included this section about temporary storage because several people have asked about it.
A final scenario that a few people have asked me about is how they might be able to store within Web projects, and under source control, files that can be used during development time (for example, design docs written in Microsoft Word or Microsoft Visio, or Adobe Photoshop .psd files for layered images), but that will be automatically excluded from any deployment or publishing steps.
A Technique to Make This Experience Much Better
Microsoft ASP.NET 2.0 supports the concept of "build providers." These are classes that implement the System.Web.Compilation.BuildProvider base class contract, and that can participate in build operations, both in Visual Studio 2005 at development-time, and in ASP.NET at runtime. Developers are free to build and implement their own BuildProviders, in order to add their own custom semantics to processing files within ASP.NET. For example, you could create an .orm file extension for files that contain XML, to declaratively represent an OR mapping database relationship. Your provider could then dynamically generate strongly typed classes that were included in the Web anytime one of these files was added to the project—and you would get both intellisense within Visual Studio 2005 at design-time, and also full runtime support.
One of the built-in build providers in ASP.NET 2.0 is called the IgnoreFileBuildProvider. Its semantics are such that it ignores whatever file extension is mapped to it, and that it also automatically prevents that file from being deployed during a publish Web operation or a compilation operation.
Developers can then use this feature to add extensions to the web.config file in their local Web projects, and effectively block any file-type they want from being deployed by Visual Studio. For example, if I wanted to prevent all .doc (Word), .psd (Photoshop), and .vsd (Visio) files from ever being deployed, I would add the following section to my web.config file.
<configuration> <system.web> <compilation> <buildProviders> <add extension=".doc" type="System.Web.Compilation.IgnoreFileBuildProvider" /> <add extension=".psd" type="System.Web.Compilation.IgnoreFileBuildProvider" /> <add extension=".vsd" type="System.Web.Compilation.IgnoreFileBuildProvider" /> </buildProviders> </compilation> </system.web> </configuration>
I am then free to add and check in these file-types anywhere in my project if I want to do so—and they can be used/modified/accessed throughout the development lifecycle—but they will be excluded anytime a build is produced.
Many possible techniques help manage the "extra" files that your Web project needs. You can put the excess files in their own virtual directory, mark them as hidden in Visual Studio, or use the BuildProvider model to change how Visual Studio handles them. Each technique helps you manage multiple files, as well as files you don't want in your version control system.