Using IIS with Microsoft Visual Studio 2005 and the New Web Project System
Product Unit Manager, Web.NET
Microsoft Visual Studio 2005
Microsoft Internet Information Services
Microsoft ASP.NET 2.0
Summary: Describes how Microsoft Visual Studio 2005 works with Microsoft Internet Information Services (IIS) to manage Web projects. (11 printed pages)
Note This article originally appeared on Scott's blog. Join in the discussion there.
Quick Review: How Does IIS Map Applications and Sites?
What Does ASP.NET Do with Applications?
How Do You Open a Web Application with Visual Studio 2005?
Strategies for Web Project Management with IIS and Visual Studio 2005
Versioning Applications Using ASP.NET 2.0
Microsoft IIS supports hosting multiple "sites" on a server. These sites are defined as a unique IP address, hostname, and/or port address combination. For example, my site (www.scottgu.com), is a site with an IP address (220.127.116.11), a hostname (www.scottgu.com), and a port number of 80 (the default HTTP port). Nikhil's site (www.nikhilk.net) is another site on the exact same Web server machine. It has the same IP address (18.104.22.168) and port number (80) as my site, but it has a different hostname binding. As long as one of these three things (IP address, hostname, port number) is different, each site can be differentiated and mapped separately on IIS.
When you register a site with IIS, you specify a parent directory for the default site content to live under. When IIS is installed, the default site is typically mapped to the c:\inetpub\wwwroot\ directory. If you place a test.htm file immediately underneath this directory and access http://localhost/test.htm, you will retrieve the file from the Web server. You can have any number of physical directories and subdirectories you want underneath a site root.
IIS also supports the concept of virtual directories (commonly called vdirs) under sites. These are logical directories from a URL namespace perspective, but they do not have to be backed by a physical directory with the same name or location on disk. For example, I could create a directory called app1 that maps to c:\inetpub\app1 and that contains a test2.htm file, and create a virtual directory in IIS that mapped it underneath the default site.
When I do this and request the following URLs, the Web server will fetch the indicated files.
http://localhost/test.htm -> c:\inetpub\wwwroot\test.htm http://localhost/app1/test2.htm -> c:\inetpub\app1\test2.htm
Note that wwwroot and app1 are peer directories in this case. Even though the logical URL structure has app1 underneath the root Web site, there is no requirement to physically structure the files this way (although I could if I wanted to).
IIS also then supports the concept of applications on servers. These are the same as virtual directories, except that they have some extra metadata stored in the IIS metabase configuration store associated with them. With IIS 6, they also support the ability of administrators to map them to be handled in different application pools (which are our worker processes), for greater reliability and process isolation.
IIS applications can map to physical directories mapped underneath the site root, or to directories outside of the site root. They can also be nested multiple layers deep, as shown in the following example.
http://www.testsite.com/ -> c:\www.testsite.com\wwwroot (the "root site" app) http://www.testsite.com/app1 -> c:\www.testsite.com\app1 http://www.testsite.com/app2 -> c:\www.testsite.com\app2 http://www.testsite.com/app3 -> c:\www.testsite.com\wwwroot\app3 http://www.testsite.com/app3/app4 -> c:\www.testsite.com\wwwroot\app3\app4
Note that the root application (http://www.testsite.com/), app1 (http://www.testsite.com/app1), and app2 (http://www.testsite.com/app2) are peer directories in the physical file-system hierarchy. App3 and app4 are then physically stored underneath the wwwroot directory (with app4 actually being nested under app3). The key thing to remember is that it is the IIS bindings, and not the file-system, that determines application scopes and boundaries—an administrator can configure things however he or she wants.
In the IIS Admin Tool, the above mapping structure would appear as shown in Figure 1.
Figure 1. IIS Administration Tool (click the image for a larger picture)
Note Just to confuse things, in the IIS Admin Tool, when you right-click and choose Create Virtual Directory underneath a site, you are actually creating an application (specifically: a virtual directory that has the app metadata set). If you want it to really be a "vanilla" virtual directory with no app semantics, you should open up the property pages on the newly created application, and click the Remove button on the Virtual Directory tab. This actually doesn't delete the virtual directory—it just removes the app metadata and depromotes it to be a normal virtual directory. And no, this isn't very logical or intuitive...
Microsoft ASP.NET uses the IIS application metadata flag (stored in the IIS metabase configuration system) to identify application boundaries, and applies special semantics to content hosted within them. Specifically, when a directory is marked as an application, ASP.NET does a few things:
- It allows a \bin directory to be defined and used immediately underneath the application root directory to resolve assembly references.
- It allows "application-level" settings such as authentication to be configured and set in a web.config configuration file.
- It allows a global.asax file to be defined to handle global "application-level" events (such as application_start) and module-specific events (such as session_start/end).
- In ASP.NET 2.0, it also allows additional directories to be created underneath the app root, to handle things such as data providers, class library compilation, application resource files, and so on.
ASP.NET then creates a CLR app-domain for all code running in the context of an application. This app-domain is where code-loading policy is set, how the assembly loader is hooked up to a \bin directory, and how additional code-access security permissions can be applied.
Using the above www.testsite.com application bindings as an example, this would mean that the \bin directory locations with the above apps could live in the following physical locations.
c:\www.testsite.com\wwwroot\bin c:\www.testsite.com\app1\bin c:\www.testsite.com\app2\bin c:\www.testsite.com\wwwroot\app3\bin c:\www.testsite.com\wwwroot\app3\app4\bin
Code living underneath the \app1 directory would use \app1\bin to load compiled assemblies.
Code living underneath the \wwwroot\app3 directory would use the \wwwroot\app3\bin directory to load compiled assemblies.
Code living underneath the \wwwroot directory—but not under the \wwwroot\app3 directory—would use the \wwwroot\bin directory to load compiled assemblies.
Note that these assembly-loading semantics are identical with ASP.NET 1, 1.1, and 2.0.
Microsoft Visual Studio 2005 supports multiple ways to open and edit ASP.NET Applications. Out of the box, its Open Web Site dialog box (invoked when you create or open a new Web project) has four tabs—one for opening Web projects directly off the file-system (just point to the app's root directory and go); one for browsing IIS directly; one for entering FTP credentials to open a site remotely; and one for using FrontPage Server Extensions. These four tabs are circled in Figure 2.
Figure 2. Opening a Web site from the file system (click the image for a larger picture)
The File System tab option is great if you are working on a self-contained Web project that requires no knowledge of the directory or URL structure of content outside its structure.
However, if you are using multiple nested IIS applications or special IIS virtual directory rules on your Web server to coordinate multiple applications, then you should avoid opening up these projects using the file-system Web option; instead, open them using the Local IIS or Remote Site tab options. The reason for this is that these nesting and relationship rules are stored in the IIS metabase, and in order for your application to properly run, you will want/need these IIS bindings and semantics to be handled both at runtime and inside Visual Studio 2005.
If you are coming from Visual Studio 2003, you are probably used to opening up Web sites with FrontPage Server Extensions and using a known URL. To do this with Visual Studio 2005, just complete the following steps:
- Click the File menu, and then click Open Website.
- In the Open Web Site dialog box, click the Remote Site tab (see Figure 3).
- Enter the name of the app you want to open for editing (for example, http://localhost/app1).
Figure 3. Opening a Web site using FrontPage Server Extensions (click the image for a larger picture)
Alternatively, you can also now browse, create, and open Web sites and applications configured on your local IIS server by using the Local IIS tab that is new in Visual Studio 2005. This does not require FrontPage Server Extensions to be installed on the Web server (Hooray!), and also provides a much richer tree-view of what the sites, applications, and virtual directories look like on your Web server. To use this with Visual Studio 2005, just complete the following steps:
- Click the File menu, and then click Open Website.
- In the Open Web Site dialog box, click the Local IIS tab (see Figure 4).
- Drill down and pick the appropriate sites/application to open.
Figure 4. Opening a Web site from the local IIS server (click the image for a larger picture)
Note that—just like today—you can absolutely use both a root Web site application (for example, in the above dialog box, just click www.testsite.com) as well as a nested subapplication (for example, in the above dialog box, just click www.testsite.com/app1).
Working with an IIS Web Application in Visual Studio 2005
Several people have asked what happens when you open up a Web site that has multiple nested subapplications underneath it. For example, you open up www.testsite.com (the root application), which contains three immediate subapplications (www.testsite.com/app1, www.testsite.com/app2, and www.testsite.com/app3). One of the questions/concerns people have had is whether Visual Studio 2005 now merges the directory structure of all of these apps together into a single directory structure model—which would obviously really screw up building applications and projects (since the \bin directory and application semantics should be different between all four of these apps).
The good news is that Visual Studio 2005 does the right thing and preserves the application scoping correctly. Specifically, when you open up the www.testsite.com application using the bindings we specified above, you will get a project view that looks like like the one in Figure 5.
Figure 5. Single site in a solution
The only files and folders included in the Solution Explorer are those within the root www.testsite.com application, and any nonapplication subfolders it contains (for example, in the above case, subdirectory1 and subdirectory2). When you perform a build or compile within Visual Studio 2005, only those files contained within the www.testsite.com application (and not any subapplications) will get compiled. When you build and deploy a Web project using the Publish menu item, you will only deploy those files in the www.testsite.com root application (and not any subapplications). These are the same isolation semantics as used in Visual Studio 2003.
One nice addition we have made to the Solution Explorer in Visual Studio 2005 is to have special icons for nested subapplications show up in a root application's Web project view (you can see these in Figure 5 with the app1, app2, and app3 special icons). These are intended to let a developer know that there are subapplications at this point in their logical Web space, but not get in the developer's way. These do not have any build semantics (they are completely excluded, just like Visual Studio 2003, from compilation operations), and you cannot expand them to get to their Web content. They are simply designed to let you know that a subapplication is there, and to help you get context on the broader Web structure.
Note also that, in the above example, app3 happens to be mapped to a physical directory (c:\www.testsite.com\wwwroot\app3) directly underneath the root www.testsite.com application (c:\www.testsite.com\wwwroot\). However, because it is marked as an application in IIS, Visual Studio 2005 will automatically exclude it from the www.testsite.com project and all compilation (same semantics as Visual Studio 2003). Subdirectory1 and Subdirectory2 are not marked as applications in IIS, which is why they show up as part of the www.testsite.com application (again, same semantics as Visual Studio 2003).
One other nice workflow feature added in Visual Studio 2005 is that you can double-click these subapplication icons. When you do this, you will get a dialog box (see Figure 6) that will prompt you to either open this Web application (and replace the current open solution) or to add this Web application to your currently opened solution.
Figure 6. Adding a Web site to an existing solution
For example, if I select Add the Web site to the current solution check box when I clicked the app3 icon in the Solution Explorer, I would end up with two separate isolated Web projects in my solution, as shown in Figure 7.
Figure 7. Two Web sites in an existing solution
Note that app3 is physically underneath the wwwroot application's directory on the physical disk—but, like Visual Studio 2003, I get an isolated view of each application, and each application can be built and deployed separately.
With Visual Studio 2005, you can use the same solution patterns you used with Visual Studio 2003 to manage subapplications. Typically, for nested subapplications, we see developers create a separate solution for each application—which typically contains a Web project, as well as one or more class library projects. For example, in Figure 8, I've added a data access layer (DAL) and business logic layer (BLL) into a solution that contains my www.testsite.com root application.
Figure 8. Multiple Web sites in one solution
I can then set up cross-project references and build dependencies the same way I do today, as shown in Figure 9.
Figure 9. Adjusting the build order for a Web project
I can then save out my solution file, which encapsulates all of these cross-project relationships, to disk (just like Visual Studio 2003 does today). When I open it again in Visual Studio, I will load the solution with the same settings as I left it before, and all three of my projects will open.
When I use the Publish Web option inside the IDE, it will compile the DAL project, then the BLL project, and then the Web project—and deploy the resulting binaries from all three compilations in the deployment directory I specify.
One last thing to mention on the topic of IIS and ASP.NET 2.0 is versioning. Specifically, the .NET Framework and Visual Studio fully support side-by-side with the ASP.NET 2.0 and Visual Studio 2005 releases. This means you can have Visual Studio 2003 and Visual Studio 2005 installed together on the same machine, and use Visual Studio 2003 for some projects and Visual Studio 2005 for others.
It also means that you can choose to have some ASP.NET applications on your Web server use ASP.NET 1.1, and others run using ASP.NET 2.0. This latter support is particularly interesting, because it allows you to incrementally switch over your systems to use the new features on your schedule, and does not force an "all or nothing" move. By default, when you install ASP.NET 2.0 on a machine that has ASP.NET 1.1 already installed, we do not automatically upgrade these apps to use the new version. Instead, administrators get to choose which app uses which version. Note that this fully works with subapplication solutions where, for example, you could migrate the www.testsite.com/app1 application to ASP.NET 2.0 while keeping www.testsite.com/app2 on ASP.NET 1.1, and migrate it on a different schedule.
One way we've tried to make version switching easier is by adding support for it to the IIS Admin Tool, under the new ASP.NET tab that gets installed when ASP.NET 2.0 is on the box. You can pull up this tab now on any IIS application, and choose which version of ASP.NET you want to run, using an ASP.NET version drop-down menu that will list all versions of ASP.NET installed on the system. Simply pick a version as shown in Figure 10, click the Apply button, and you've configured that app to run using it.
Figure 10. Selecting the ASP.NET version
No more messing around with ISAPI script-mappings required.
Hopefully this provides a quick summary of how you build and manage Web applications using IIS with Visual Studio 2005. If you are using Visual Studio 2003 you should find the steps pretty familiar—although hopefully the workflow is a little faster and easier than before.
About the author
Scott Guthrie co-founded the ASP.NET Team, and leads the design team responsible for architecting the product. His individual contributions include: ASP.NET Web Forms Page Architecture, ASP.NET Web Services Infrastructure, ASP.NET Compilation System, ASP.NET Distributed Session State Infrastructure, ASP.NET Deployment Architecture, ASP.NET Reliability System, and the ASP.NET HTTP Runtime Architecture. Prior to ASP.NET, Scott was a member of the IIS and Windows NT development teams.