Building and Deploying Web Application in .NET 2.0
"Building your .NET 2.0 web application is easy", you may have heard. Well, it depends on what do you mean by "build" and what do you mean by "easy". At my work place the system admins are spoiled into requiring all deployment be done with .msi files. What they want is click buttons to build the .msi file, run the .msi file on target machine and forget about it. It is developer's job to make sure all the projects are set up properly to accomplish this.
The hard way. To create *.msi file for web applications in Visual Studio .NET 2005, the "recommended" way is:
- Add an installer class to your existing web application.
- Create a separate installer project (and maybe an additional web deployment project).
- Tweak the GUI in the installer project to accept your configuration/environment settings.
- Write code in your installer class to use the configuration/environment settings properly (and to create the virtual directory, etc.).
If you have done this before you will know it is a PITA. Come on, admit it, nobody is going to laugh at you. If you have a lot of web applications, doing the above for all of them is very frustrating and depressing. The part I hate most is customizing GUI in the installer project, in my opinion it is the worst piece of technology from Microsoft.
Now what can we do about it? I worked on this problem intensively for two whole days and came up with a General Installer project that works with every web application I have (cannot guarantee it will work with all of yours though). Here is the idea:
- The installer project itself will take care of packaging all components in the web application into an .msi file.
- The installer project references a DeployHelper.dll that handles the GUI part and does most of the work for you. This DLL is independent of the web application you want to deploy. It uses a windows form to gather configuration/environment settings from user. You can customize it anyway you want.
- Information specific to your web application (such as default website, etc.) is contained in a simple Deploy.xml file.
The easy way (for me anyway). To build and deploy a web application, here is all I need to do:
- Use "open website" menu to open my web application in Visual Studio.
- Use "publish website" menu to create a precompiled website in a selected folder.
- Open the General Installer project and the precompiled website in Visual Studio.
- Modify Deploy.xml file for my web application.
- Add the precompiled website to the installer project as project output. Build.
- Run GeneralInstaller.msi on target machine.
The above steps could take a whopping 20 minutes the first time you do it. Note that you don't need to create an installer project for each web application you want to deploy. If you wish, you can make a copy of the General Installer project for each web application and customize it.
Use included batch file. Instead of running GeneralInstaller.msi directly, it is much easier to run the included batch file GeneralInstaller.bat. This file must be placed in the same folder as GeneralInstaller.msi. Using this batch file, you can install the same web application multiple times on the same machine, there is no need to uninstall a previous version.
Deploy to VISTA. If you run either the batch file or the .msi file on a VISTA machine, you will get access denied error. This can be blamed on UAC, of course. What you need is open an Administrator Console (if you don't know how, remember "Google is your friend") and run the batch file from there.
The Details
General Installer. This project is a regular windows setup project generated from Visual Studio 2005. I removed all GUI except the progress bar (you can remove that, too). Then I added two files to this project: DeployHelper.dll and Deploy.xml.
Deploy Helper. This project is a library which contains two classes: ApplicationConfiguration and CustAct. The first class is derived from System.Windows.Forms.Form which handles GUI. The second is derived from System.Configuration.Install.Installer.
The purpose for this library is to relieve the pain of customizing GUI in installer project. It also does a lot of other things which I am not going to describe in this article. Now you have full control of everything. Here is the windows form in this DLL.
Target Dir is the physical folder for the current web application.
App Name is the application name in IIS.
Web Site dropdown is used to select one of the available websites on the target machine.
Virtual Dir is the name of the virtual directory in IIS, if you leave this field empty, the web application will be installed on the root of the selected website.
Config File dropdown allows you to pick a file as web.config file for the current web application (it will replace web.config with the file you selected).
Finally, if you want to reset IIS, check the Reset IIS box before clicking the Confirm button.
Deploy.xml. Here is a sample copy of this file. It is used to store default values for the current installation.
="1.0" ="utf-8"
<Configuration>
<TargetDir>c:\TestWeb</TargetDir>
<AppName>TestWeb</AppName>
<WebSite>Default Web Site</website>
<VirtualDir>TestWeb</VirtualDir>
<WebConfigReplacement>true</WebConfigReplacement>
<AppPool>.NET 2.0 Apps</AppPool>
<DefaultDoc></DefaultDoc>
</Configuration>
Web Application Configuration
If you have only one configuration file (web.config) for all environments, then you need to set the WebConfigReplacement value in Deploy.xml to false.
I assume all configuration settings for a web application are stored in web configuration file. For each different environment, you should have a different web configuration file. These files have to be named like web_test.config, web_prod.config, etc. Otherwise DeployHelper.dll cannot handle it. You can modify DeployHelper.dll to handle configuration settings any way you want.
Note. There are a lot of other options you can set in Deploy.xml file, you need to look in the source code of DeployHelper.dll to find out.
For example, you can specify the name of your preferred application pool in the AppPool element of Deploy.xml. If an application pool with given name is found during deployment, your application will be assigned to this application pool (application pool assignment works only with IIS v6.0+).
Another example is you can specify a default document for your web application in the DefaultDoc element.
Possible Issues
- Solution File. As you may have noticed, web applications created by Visual Studio 2005 do not have project files. Some of the project options are saved in solution file (such as the default folder to publish the web application, etc.).
- Precompiled Website. Visual Studio 2005 sometimes generates different DLLs for the same web application when you try to "publish" the website. It may have a good reason for doing this but I don't really care. You can change an option to fix it, I won't bother you with the detail here.
- DLL not found error when building .msi file. This is likely caused by the above behavior of Visual Studio. If you close Visual Studio and reopen it, the problem should go away.
- Uninstall does not work as you expected. If you use the GeneralInstaller.msi file directly, after installation, the GeneralInstaller item appears in Add or Remove Programs in Control Panel. You can click that item to uninstall. However, uninstall does not remove the web application you installed. This is by design. I did not write any code in DeployHelper.dll to delete the files and virtual directory, etc. It is recommended to use the included GeneralInstaller.bat file to install your web application, it will remove the GeneralInstaller item from Add or Remove Programs right away. Please note that the same web application can be installed on the same machine multiple times (in different physical and virtual directories).
History
- 09/09/2008: Set default document for web application in Deploy.xml file
- 08/30/2008: Added note for deploying to VISTA
- 08/28/2008: Added support for application pool assignment
- 08/27/2008: Modified article text, updated code
- 08/15/2008: Initial version implemented
| You must Sign In to use this message board. |
|
|
 |
|
 |
I just learned to used asp.Net When i want to displayed it to my friend in his computer,it didn't show Could you tell me the detailed steps ?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Am I the only person who simply copies the files the production directory?
I didn't get any requirements for the signature
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Yes! I would love to do that. But I am not allowed to come within two miles of the production servers nor can I remotely logon, except when there is a serious production issue that causes the whole website shutdown.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
That makes sense.
By the way, I'm using a global error handler class that emails me when an error occurs. I have found that if I don't pre-compile and I copy the source, I get the actual line number of the code that caused the exception in the exception message. It makes life easy.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
ToddHileHoffer wrote: By the way, I'm using a global error handler class that emails me when an error occurs. I have found that if I don't pre-compile and I copy the source, I get the actual line number of the code that caused the exception in the exception message. It makes life easy.
Can user see the exception? I hope you don't have exceptions like the following:
Error in line 101 of source file Login.aspx.cs: User 'Admin' failed to login. The password '1234' does not match the value 'password' in the database.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
LOL, no we redirect the user to an error page. What's funny though is I have seen the asp.net error page on commercial sites. I even saw it on Microsoft.com once.
I didn't get any requirements for the signature
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I was encountering some issues when running your code with my own additions for the ApplicationPool creation on a 64 bits system. I asked about it in a 64 bits forum, because I thought the code was just fine. The problem was that when I enable the "New Folder" button on the BrowseFolderDialog it worken on 32 bit systems but not 64 bit systems.
There they told me that the code for the BrowserDialog violated COM requirements and that it should stay within the same thread. I`ll adjust this in the code I am using now. But I thought I'd let you know. By the way, the forum post can be found at: http://forums.msdn.microsoft.com/en-US/netfx64bit/thread/d5d0eb76-c1f9-450a-ac76-055f50c65bc2/[^]
I also posted at the IIS forum because it seems that the write permission is incorrectly set for the Virtual Directory on 64 bit systems. But that post is pending moderation. I`ll also post that link when the post is approved.
Philip Wagenaar
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
I hide the Make New Folder button on folder browse dialog because I think it is not needed. If you specify TargetDir as c:\NonExistentParentFolder\MyFolder, it will work fine: all parent folders will be created for you.
Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Philip Wagenaar wrote: ok, but thread issue still exists.
???
The following lines make the Folder Browser Dialog run in a STA thread:
Thread thread = new Thread(new ThreadStart(BrowseDialog)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join();
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
 |
After building, a copy of deploy.xml file is packaged into the .msi file. So if you change the file again, you need to rebuild.
Philip Wagenaar wrote: It's also very easy to add code to create and configure applications pools
I will take a look to see if I can add a feature to my tool. Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Would be nice if you could place Deploy.xml in the same folder as the MSI and if so it would overrule the Deploy.xml packaged into MSI itself at runtime.
I tried to add this myself but I haven't found a fail proof way to always find the folder where MSI is located.
Philip Wagenaar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, Philip. I updated the code to add support for Application Pool Assignment. If you specify the name of your preferred pool in the <AppPool> element in deploy.xml, then your web app will be assigned to that pool. The assumption is IIS 6.0 is used and the app pool already exists (the code does not create a new app pool).
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Nice!
I already added it myself to your example. I also added code to create an Application Pool and set some custom settings for the Application Pool that are specific for my situation:
DirectoryEntry newpool; DirectoryEntry apppools = new DirectoryEntry(metabasePath); newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool"); newpool.CommitChanges();
newpool = new DirectoryEntry(metabasePath + "/" + appPoolName);
newpool.Properties["PeriodicRestartSchedule"].Value = "03:00"; newpool.Properties["PeriodicRestartTime"].Value = "0"; newpool.Properties["IdleTimeout"].Value = "0";
newpool.CommitChanges();
A list of all available properies can be found at: http://msdn.microsoft.com/en-us/library/ms525950.aspx[^]
Philip Wagenaar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Philip Wagenaar wrote: I already added it myself to your example.
I added similar code to create the app pool if it is not there already, after that, I thought about it: Sicne the pool is meant to be shared, logically it should probably be created separately. Plus some parameters/properties of the pool need to be configurable, if I put those in Deploy.xml file, there is a risk of installing one application will over-write things set by the installation of another application.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I always create a seperate AppPool for each applications. You could also check if the AppPool already exists. But then you might just be re-writing IIS Manager into your setup
Philip Wagenaar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Philip Wagenaar wrote: But then you might just be re-writing IIS Manager into your setup
It feels like it now. I better stop.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Unless you are in a crazy environment where a system administrator(who knows absolutely nothing about web apps) is installing web applications, which should not be the case 99% of the time, MSI is useless I don't even think you can make a MSI install unattended yet so there is less of a use for them.
Great Atricle but I think you might be in the few who even uses installer projects for web apps.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
How do you deploy a web application? Just wondering.
I don't like .msi file myself, but we have been required to use it for our web applications. It does sound simple for system administrators and it can be made unattended, too (although we have administrators install manually).
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I also agree that MSI installation of an ASP.NET application can make deployement more simple. Of course it might not be suiteble for all situations.
For example, if you need to register DLL's, set up database connections and test the connection you could include these in your Custom Actions.
Another way would be to create a wizard install that is shown the first time you start your ASP.NET application: http://www.codeproject.com/KB/aspnet/WebInstaller.aspx[^]
Philip Wagenaar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|