If you’re developing ASP.NET applications against the Microsoft .NET Framework without the benefit of Visual Studio .NET, most (if not all) of your deployment work will be manual. The great news is that ASP.NET applications are simple to deploy. Even if you are using Visual Studio .NET, you might need to or want to deploy your Visual Studio .NET ASP.NET application manually.
To successfully deploy an ASP.NET application, the first thing you need is a target directory on the server that will host the application. You must set up this directory in IIS as an application root if you want to use the automatic loading of assemblies in the bin subdirectory or use a Global.asax file if you want to have a root Web.config file for the application. (You can’t set certain configuration sections below the application level, and they will cause errors if used in a Web.config file that resides in a subdirectory.)
Once you’ve set up the target directory in IIS (mapped to a physical folder on the host machine), you’re ready to copy all the necessary files to the target directory. You can do this by using any number of commonly available tools, from the XCOPY command to WebDAV. You can even drag-and-drop files to and from a network share using Micorosoft Windows Explorer.
If you’re using code-behind in your Web Forms pages or user controls, you’ll need to decide whether to deploy the code-behind class files containing your source code to the target server. If you’re using the Src attribute of the @ Page or @ Control directive to have ASP.NET dynamically compile your code-behind classes, you have to deploy the class files, or the application will not function. If you want to avoid deploying the code-behind class files, you can use the Inherits attribute of the @ Page or @ Control directive instead of the Src attribute. Using the Inherits attribute requires you to manually compile your code-behind classes and put the resulting assemblies in the application’s bin subdirectory. Projects created with Visual Studio .NET will be created using the Inherits attribute of the @ Page or @ Control directive. As a result, you must build the project before deploying it, whether you deploy the project manually or by using Visual Studio’s deployment tools.
Deploying static content (such as HTML pages and images), Web Forms pages, user controls, and code-behind classes is as simple as copying them from the development application directory to the deployment target directory. For example, you would use the following command to deploy content from a local directory C:\inetpub\wwwroot\myDevApp to a remote directory for which a mapped drive, X:, has been created:
xcopy c:\inetpub\wwwroot\ASPNetApp1 x:\ /E /K /O
The parameters passed to XCOPY are as follows:
/E specifies that all subdirectories are to be copied, whether empty or not.
/K specifies that file and directory attributes on the destination should be set to match the source.
/O specifies that ownership and ACL information should be copied to the destination. This is useful when using domain accounts to set ACLs.
You can find out about all of the command-line parameters available with XCOPY by executing XCOPY /?.
One of the areas of great improvement in deployment is .NET managed assemblies over COM components. With classic ASP applications that used custom COM components, not only did you need to copy the component file to the machine on which the application was being deployed, but you also needed to register that component in the system registry, which was difficult to do remotely. Additionally, registering a component made that component available to any application on the server, which is not allowed in a shared server environment.
Because .NET assemblies are self-describing and assemblies are private to an application by default, you can simply copy an assembly to the bin subdirectory of an application and it will be available for use by the application automatically. Private assemblies do not need to be registered to be used, and they are available only to the application in whose bin directory they reside.
The exception to the rule of XCOPY deployment applies to assemblies that you want to make available to more than one application on the server without having multiple copies of the assembly (one for each application). These assemblies need to be installed in the GAC. Remember that assemblies installed in the GAC must be strongly named. You can do this by using the al.exe command-line tool. Once you have a strongly named assembly, you can install it into the GAC in several ways:
Microsoft Windows Installer 2.0 This is the preferred method for installing assemblies into the GAC because it performs reference counting and provides transactional installation, neither of which are available with the other options. See the Windows Installer documentation for more information on packaging and installing applications with Windows Installer 2.0.
gacutil.exe This command-line utility lets you add assemblies to the GAC, remove assemblies from the GAC, and list the contents of the GAC.
Windows Explorer The .NET Framework installs a shell extension that lets you simply drag-and-drop strongly named assemblies into the GAC from any Windows folder. The GAC is located at %WinDir%\assembly.
One nifty thing about global assemblies that compensates for the additional overhead of installing and removing them from the GAC is that they can contain versioning information. This allows two or more versions of the same assembly to be executed side by side, and it allows client applications to request the version of an assembly they want to use, or to accept the latest revision of an assembly.
In addition to the problems of registering COM components, IIS locked any COM component as soon as it was called. Because of this, replacing or updating a COM component often required stopping the IIS Web service, unregistering the old component, copying over the new component, registering the new component, and restarting the Web service. For many applications, this meant an unacceptable amount of downtime.
With private assemblies, this is no longer a problem because of the way ASP.NET loads assemblies. Unlike IIS under classic ASP, which loaded a component into memory and locked it on disk until the Web application (or IIS) was shut down, ASP.NET first makes a shadow copy of each assembly file and then loads and locks the shadow file instead of the original. ASP.NET then monitors the original files for changes. If changes are detected, ASP.NET fulfills any existing requests with the current copy of the assembly, and then it loads the new assembly and fulfills new requests using the updated assembly, discarding the old assembly. This allows you to easily update any private assembly used by your application without needing to shut down the Web server, even temporarily.
Once you’ve copied your content and assemblies to the target directory, it’s a good idea to double-check the IIS permissions on any subdirectories in the application. Fortunately, ASP.NET actually takes care of one of the most important checks for you. It automatically removes all permissions on the bin subdirectory of the application, effectively preventing the contents of the directory from being listed, read, downloaded, or executed.
Now, preventing IIS from executing the assemblies on behalf of clients might sound like a bad thing, but it’s not. In fact, when a request comes in for a resource that ASP.NET handles, such as an .aspx, .ascx, or .asmx file, IIS simply hands the request over to ASP.NET, which processes the request from there. Since ASP.NET alone is responsible for loading assemblies, preventing IIS from attempting to execute assemblies is a good thing.
If you have subdirectories that contain static content, such as images, you should ensure that the only permission allowed on these subdirectories is Read.
Most important, if you need to allow users to upload content to your Web application, it is absolutely essential that you set up a separate subdirectory for this purpose, and set only the Write permission. Read must not be allowed on this subdirectory, nor should you set the Execute permissions to anything other than None. Failure to follow these guidelines could allow an attacker to upload and execute hostile code in your application.
You can view and modify the IIS permissions for any directory by right-clicking the directory name in Internet Services Manager and selecting Properties. The permissions are set in the Directory (or Virtual Directory) tab, which is shown in the following illustration.