A number of people have asked me questions through my blog over the last few days about how VS 2005 uses and handles IIS (especially in cases of nested applications and virtual directories). This blog entry provides more information on how this works, and hopefully clears up a few questions people might have.
Quick Review: How does IIS map applications and sites?
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 (22.214.171.124) a hostname “www.scottgu.com” and a port number of 80 (the default http port). Nikhil’s site (www.nikhilk.net) is also another site on the exact same web server machine. It has the same IP address (126.96.36.199) and port number (80) as my site, but 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 sub-directories you want underneath a site root.
IIS also supports the concept of “virtual directories” (commonly called "vdirs") under sites, which are logical directories from a url namespace perspective, but which 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 which 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 below urls, the web-server will fetch these 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 website, 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 IIS6 they also support the ability for 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.
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 in this sample the root application (http://www.testsite.com/) and 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, which determines application scopes and boundaries – an administrator can configure things however they want.
In the IIS Admin Tool, the above mapping structure would look like this:
Note: Just to confuse things, when you use the IIS admin tool and right-click and choose “Create Virtual Directory” underneath a site, you are actually really creating an “application” (specifically: a virtual directory that has the app meta-data 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 under the virtual directory tab. This actually doesn’t delete the virtual directory – it just removes the app meta-data and de-promotes it to be a normal virtual directory. And no – this isn’t very logical or intuitive…
What does ASP.NET do with applications?
ASP.NET uses the IIS application meta-data 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:
1) It allows a \bin directory to be defined and used immediately underneath the application root directory to resolve assembly references.
2) It allows “application-level” settings like authentication to be configured and set in a web.config configuration file.
3) It allows a “global.asax” file to be defined to handle global “application level” events (like application_start, and module specific events like session_start/end).
4) In ASP.NET V2.0 it also allows additional directories to be created underneath the app root to handle things like data providers, class library compilation, application resource files, etc.
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 (and 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 these physical locations:
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 V1, V1.1 and V2.0.
How Do You Open a Web Applications with VS 2005?
VS 2005 supports multiple ways to open and edit ASP.NET Applications. Out of the box its “Open Web Site” dialog (invoked when you create or open a new web project) has four tabs – one to open web projects directly off the file-system (just point to the app’s root directory and go), by browsing IIS directly, by entering FTP credentials to open a site remotely, and by using FrontPage Server Extensions (note: I've circled the 4 tabs in the screenshot below).
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 – and instead open them using the “Local IIS” or “Remote Site” tab options. The reason for this is because these nesting and relationship rules are stored in the IIS metabase, and for your application to properly run you will want/need these IIS bindings and semantics to be handled both at runtime and inside VS 2005.
If you are coming from VS 2003 you are probably used to opening up web-sites with FrontPage Server Extensions and using a known URL. To-do this with VS 2005, just follow the following steps:
1) Select File->Open Website off the file menu
2) Select the “Remote Site” tab on the “Open Web Site” dialog (see below)
3) Enter the name of the app you want to open to edit (example: http://localhost/app1)
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 new in VS 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 VS 2005, just follow the following steps:
1) Select File->Open Website off the file menu
2) Select the “Local IIS” tab on the “Open Web Site” dialog (see below)
3) Drill down and pick the appropriate sites/application to open
Note that – just like today – you can absolutely use both a root web-site application (for example: in the above dialog just click on www.testsite.com) as well as nested sub-application (for example: in the above dialog just click on www.testsite.com/app1).
Working with an IIS Web Application in VS 2005
Several people have asked what happens when you open up a website that has multiple nested sub-applications underneath it. For example: you open up www.testsite.com (the root application), which contains three immediate sub-applications (www.testsite.com/app1, www.testsite.com/app2, and www.testsite.com/app3). One of the questions/concerns people have asked is whether VS 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 4 of these apps).
The good news is that VS 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 this:
The only files and folders included in the solution explorer are those within the root www.testsite.com application, and any non-application sub-folders it contains (for example in the above case “subdirectory1” and “subdirectory2”). When you perform a build or compile within VS 2005 only those files contained within the www.testsite.com application (and not any sub-applications) 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 sub-applications). These are the same isolation semantics as used in VS 2003.
One nice addition we have made to the solution explorer in VS 2005 is to have special icons for nested sub-applications show up in a root application’s web project view (you can see these in the screen-shot above with the app1, app2, and app3 special icons). These are intended to let a developer know that there are sub-applications 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 VS 2003 from compilation operations), and you can not expand them to get to their web-content. They are simply designed to let you know a sub-application 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, VS 2005 will automatically exclude it from the www.testsite.com project and all compilation (same semantics as VS 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 VS 2003).
One other nice workflow feature added in VS 2005 is that you can double-click on these sub-application icons. When you do this you will get a dialog pop-up that will prompt you to either open this web application (and replace the current open solution) or to add this web application to your current opened solution:
For example, if I choose “add the web site to the current solution” when I clicked the “app3” icon in the solution explorer, I would end up with two separate isolated web projects in my solution:
Note app3 is physically underneath the wwwroot application’s directory on the physical disk – but like VS 2003 I get an isolated view of each application, and each application can be built and deployed separately.
Strategies for Web Project Management with IIS and VS 2005
You can use the same solution patterns you used with VS 2003 to manage sub applications with VS 2005. Typically for nested sub-applications 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 the below sample I’ve added a data access layer (DAL) and business logic layer (BLL) into a solution that contains my www.testsite.com root application.
I can then setup cross project references and build dependencies the same way I do today:
I can then save out my solution file which encapsulates all of these cross-project relationships to disk (just like VS 2003 does today). When I open it again in VS 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, then compile the web project – and deploy the resulting binaries from all three compilations in the deployment directory I specify.
Versioning Applications using ASP.NET 2.0
One last thing to mention on the topic of IIS and ASP.NET 2.0 is versioning. Specifically, the .NET Framework and VS fully support side-by-side with the .NET 2.0 and VS 2005 releases. This means you can have VS 2003 and VS 2005 installed together on the same machine, and use VS 2003 for some projects and VS 2005 for others.
It also means that you can choose to have some ASP.NET applications on your web-server use ASP.NET V1.1, and others run using ASP.NET V2.0. This later support is particularly interesting – as 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 V1.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 sub-application solutions -- where for example you could migrate the www.testsite.com/app1 application to V2 while keeping www.testsite.com/app2 on V1.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 a version drop-down that will list all versions of ASP.NET installed on the system. Simply pick a version, hit the apply button, and you’ve configured that app to run using it.
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 VS 2005. If you are using VS 2003 you should find the steps pretty familiar – although hopefully the workflow is a little faster and easier that before.
Let me know if this makes sense or if you have any questions.