Chapter 13. Deploying the Site

You've come to the end of the development: your site is ready, you've tested it locally and it all works fine, and now you have to publish it online. If you've ever had any experience with older legacy ASP/COM applications, and later with ASP.NET 1.x applications, you already know that .NET made deployment much easier: you no longer had any COM components to register, or shared components that might overwrite an existing version and thus break other applications. For pure ASP.NET applications, it may suffice to do an XCOPY of all your deployment-related files (such as .aspx, .dll, .config, and image files) to the remote server, and then deploy the database. However, in the real world, things usually tend to get a little more complex than that because you have constraints and company policies to respect regarding the deployment of your application. Database deployment and configuration are also nontrivial, and you should consider this carefully before you start rolling out the site. In this final chapter, I will guide you through all of the different options to successfully deploy your website's files and the database, explaining why and when some techniques are more suitable than another.

Problem

The problem described and solved here was a real problem that I faced while completing the sample site. I wanted to put the site online somewhere so that potential readers could browse it and consider whether it was worth the purchase, and so that I could show it to clients and colleagues during presentations about ASP.NET 2.0.

Not having a private dedicated server connected to the Internet available for this project, I chose to deploy the site to a typical shared web hosting service that uses servers running Windows Server and supports ASP.NET 2.0 and SQL Server. Most of these Microsoft-centric web hosting companies now support this platform, and several of them offer plans that cost as little as $10 per month. When evaluating hosting service companies, you need to ensure that they offer you enough disk space and bandwidth, and that you factor in the cost of SQL Server (some companies charge extra for this). Of course, your specific hosting requirements may vary according to the type of project you're working on. For large or high-usage sites, or just sites that require high availability, you'll want dedicated servers configured as a web farm (whereby a number of servers are running the same applications and load-balancing is used to determine which server will process a specific web request).

IIS and ASP.NET is a very scalable web platform where most websites have a very over abundant hardware allocation. Marcus Frind has a great discussion about his experiences with ASP.NET 2.0 with the demand Plentyoffish.com receives, http://plentyoffish.wordpress.com/2006/06/10/microsoft-aspnet-20-performance. This article is a little outdated. With the release of IIS 7.0 the numbers are even better.

Also consider that our sample website is 100% pure ASP.NET, with no legacy COM components, COM+ services, or Windows services: these things would require special installation and are usually not allowed by basic low-cost hosting plans. In our case, we don't need the benefits of a dedicated server or web farm, so a shared hosting plan is fine. For the situation just described, the problem statements are pretty simple to formulate:

  • What files do I need to deploy?

  • How do I deploy those files?

  • How can I protect my source code against prying eyes once the website has been published on a shared remote server?

  • How do I move my local SQL Server Express database into a full SQL Server 2005 database (when SQL Server Express has been used to develop the site)?

  • How do I create an installer that automates the whole site's setup, which would be useful if I sold the website as a product, or if I wish to deploy to a dedicated web server?

In the following pages you'll find answers for all of these questions.

Design

The complete deployment is basically split into two parts: deploying the database and deploying the site's files. If your web server supports SQL Server Express (only recommended for small workgroups), deploying the database is as simple as copying the contents of the App_Data folder to the remote server's App_Data folder, and the .mdf and .ldf files will automatically be attached to the remote SQL Server Express that is installed on the web server! However, production deployment normally requires a full-featured SQL Server (not the Express edition), for security, performance, and scalability reasons. Because of this, you need to find some way to turn the current SQL Server Express database into a SQL Server database. As for the site's files, you have different options here, as you'll see shortly.

Make the effort to know the version the destination SQL Server. Most corporate environments are still using SQL Server 2005 or even 2000. There is nothing in the Beer House's database that should cause any problems with these earlier versions, but you may have to adjust the database properties to the proper version.

One important point to consider is the fact that we did all our development using VS2008's integrated web server and not IIS. The integrated web server is fine for local testing but your site must be tested on IIS before deploying to a production server. Therefore, before deploying the site to the remote server, you'll first test it on a local installation under IIS, replicating the configuration you have on the production server as much as possible. This will be a test of your deployment procedures and configuration, in addition to the obvious test of your code and pages. The following sections provide a detailed tutorial of the steps to take for a complete local deployment of the database and the application, and later you can follow the same steps for production deployment.

There are several common website deployment options: shared hosting, dedicated hosting/co-location, or an internal infrastructure. Shared hosting is great for the vast majority of websites because they have relatively low traffic and have minimal disk space needs, but there is limited administrative control over the server. A shared hosting environment has one instance of IIS running, with numerous websites. Think of it as leasing an office in a large office building. You have a key to your office but share the vast majority of infrastructure with other tenants. Some hosting companies stuff as many sites on the server as it physically can hold; often they will oversell the capacity on the server to make it profitable. It pays to do background research on any company you are thinking of choosing before committing your site to them.

Dedicated hosting provides much more control over the server and provides a more private experience, since there is no one else sharing the machine. You should note that it is very common for large hosting companies to offer virtual dedicated servers. This is not a dedicated physical server but a dedicated virtual server with several other dedicated virtual servers running on the same hardware. Typically, this will use a technology like Windows Hyper-V as the core operating system and run several virtual machines at once. You should also determine which type of dedicated hosting you are using. Virtualization is a great way to manage servers because the operating system image is not bound to the physical hardware and can be easily backed up and restored in the case of a hardware failure. Co-location is similar to renting a dedicated server environment from a hosting provider, except that you own the box and only rent the cabinet space, power, and bandwidth from the data center. Often it is slightly cheaper, but it places some extra responsibilities on you that you would not have in shared and dedicated environments.

Finally, most large enterprise operations have a dedicated IT staff and possibly a data center. They may actually utilize a third party and use the dedicated or co-location solutions described earlier. Either way, there will typically be a set of policies, procedures, and rules that must be followed for deployment. Often they will not allow you any sort of access to the servers hosting your database and site. You will instead have to provide them with the database or database script, the website files, and detailed instructions on installation. Understanding how to use the tools provided by SQL Server and Visual Studio 2008 should make this process much easier for any of the possible hosting scenarios.

Deploying the Database to SQL Server 2008

When using a shared hosting service, you will typically have an empty database on a shared SQL Server database, which you can access remotely through the SQL Server Management Studio (SSMS) desktop application (the new replacement for both Enterprise Manager and Query Analyzer), or with an online web front end provided by the hoster. However, they usually don't give you the access rights to upload an .MDF file and attach it by running the sp_attach_db stored procedure (which was introduced in Chapter 3), because that would require administrative rights, and nor do you have permission to restore a database from backup files generated on your local server. Your hosting company's support staff may do this for you if you make a special request, but they may not. However, most hosting companies have some kind of web application that lets you run queries and SQL scripts on your remote database; and as mentioned earlier, they do allow you to connect remotely with SSMS (SSMS is usually better than the hosting company's web application).

When deploying to a particular server under your control (as opposed to a shared hosting company server), you can just create a new database on the server, and then create a new login and give that login permissions in your new database. This is not an end-user account; it's the account that your website will use to access the database. The following SQL commands will do this (please select a good password in place of 'password'):

USE Master
GO
CREATE DATABASE TheBeerHouse
GO
USE TheBeerHouse
GO
EXEC sp_addlogin 'BeerHouseUser', 'password', 'TheBeerHouse'
EXEC sp_grantdbaccess 'BeerHouseUser', 'BeerHouseUser'
EXEC sp_addrolemember 'db_owner', 'BeerHouseUser'
EXEC sp_addrolemember 'db_datareader', 'BeerHouseUser'
EXEC sp_addrolemember 'db_datawriter', 'BeerHouseUser'
GO

To set up a remote database just like your local database, you need to create all its objects: tables, stored procedures, views, triggers, indexes, constraints, roles, and so forth. In addition to your own objects, you also have to re-create all the objects required by the SQL Server providers used by ASP.NET for features such as membership, profiling, personalization, and web events.

There are many ways to create all the database objects in a new remote database, but the following are among the best options (only the first option is covered in detail due to space constraints):

  1. Make SQL scripts from your development server and execute those scripts on the new server (the code download for this book has SQL scripts, or you can make them yourself).

  2. Use SQL Server Management Studio (SSMS) to copy the whole database from your local development database directly to the new server.

  3. Copy your .mdf (database file) and .ldf (log file) from your local computer to the remote computer, and attach them to the remote instance of SQL Server.

  4. Use SSMS or SQL commands to create a backup of your local database to a file, and restore from the file on the new server.

  5. Use the new SQL Server Integration Services, which is a powerful and flexible replacement for the older DTS services.

  6. Write your own data migration program using the SQL Server Management Objects (SMO), which is a new set of classes that enable you to manipulate SQL objects from a .NET program (SMO replaces the older SQL-DMO COM objects).

Option 2 is the easiest, but it requires you to have administrator access on both computers (not possible for a shared hosting deployment). In fact, options 2, 3, and 4 are normally not available for shared hosted sites, and options 5 and 6 may not be available in some shared hosting environments. This leaves option 1 as the most portable option that will always work for every situation. The only problem with option 1 is that you can't script data for image columns (used in the aspnet_profile table), so you need an alternate way to populate the data once the objects have been created.

Most of the aforementioned options are easiest to implement using SQL Server Management Studio (SSMS) on your local development computer, where both the local and remote databases are registered in the configuration. Either edition of SSMS (full or express) can be used for this purpose. Because of space constraints here, I can't cover SSMS in detail, but I'll walk you through some of its most useful features that are helpful for deployment.

Create the Standard ASP.NET Objects

There's a convenient shortcut for creating the ASP.NET required objects (for profiles, membership, etc.): if you remember from Chapter 4, all those objects can be created by executing the aspnet_regsql command-line tool and specifying the target server and database. Of course, this requires that you can access the remote SQL Server over the Internet (i.e., you can connect to it from your desktop and not only from the web server running your site). This is the syntax you can use to install the ASP.NET tables on a remote server at a specified IP address:

aspnet_regsql.exe -U username -P password -S 111.222.333.444 -d DBname -A all

An alternative, in case you can't access your remote database this way, is to use the hoster's database manager (or SSMS) to manually run a set of SQL scripts to create those objects. Microsoft has provided these scripts under the C:WINDOWSMicrosoft.NETFrameworkv2.0.50727 folder. The files have not changed since ASP.NET 2.0 was released. These script files must be run in the following order:

  • InstallCommon.sql

  • InstallMembership.sql

  • InstallPersonalization.sql

  • InstallProfile.sql

  • InstallRoles.sql

  • InstallWebEventSqlProvider.sql

Note

Important! All of these scripts reference a database named aspnedb. Your database is probably named differently, so you'll need to edit the scripts to specify the name of your database (you should make copies and only edit the copies, of course).

As you can see, it's very easy to create the standard objects, but you normally don't have to do this as a separate step. Instead, you can just script these objects along with your own objects, as you'll see in the following section.

Script All Your Database Objects

You can generate SQL CREATE scripts from your local development database, and then execute them on the remote database server. Although Visual Studio 2008 is not quite as good as SSMS when it comes to generating scripts, it can be used for this. Using Visual Studio 2008, open the Server Explorer Window (select View

Script All Your Database Objects
Figure 13-1

Figure 13.1. Figure 13-1

Script objects can be created one by one by browsing the local database on Visual Studio's Server Explorer window and clicking the Generate Create Script to Project command from the object's context menu, see Figure 13-2.

Although this method of creating SQL scripts works fine, it's not the most convenient approach because you have to generate scripts one object at a time, in separate files, and then merge everything.

It's easier to generate one script that contains all the objects using SSMS. If you loaded the .MDF data file on your computer but haven't attached it to the local database yet, you can do this by means of the Attach command from the Databases item's context menu (see Figure 13-3).

From the dialog box that pops up you select the .MDF file to attach and the name you want to give it in the SQL Server 2008 instance. For example, in Figure 13-4 the AdventureWorksLT.MDF file is being named after AdventureWorksLTDemo.

If you receive an error when attaching the file from SQL Server's dialog box, ensure that it is not being used by some other process, and is not already attached to Visual Studio's Server Explorer tool. In the former case, just stop the guilty process; in the latter case, simply detach the file by means of the Detach comment, reachable from the database file's context menu.

Figure 13-2

Figure 13.2. Figure 13-2

Figure 13-3

Figure 13.3. Figure 13-3

Figure 13-4

Figure 13.4. Figure 13-4

Once the database is attached to your local database, you can launch the Script Wizard by selecting the database from the Explorer window and then selecting Tasks

Figure 13-4

This launches the Script Wizard, which allows you to select the objects you want to include in the script. You can select all the objects by checking the "Script all objects in the selected database" option at the bottom of the dialog. In the next step, you can choose to script all tables, stored procedures, user-defined functions, roles, and views, and you have many more options to optionally script primary and foreign keys, check constraints, triggers, indexes, and so on (see Figure 13-6). This includes all the objects required by the ASP.NET features and providers, so if you follow this approach there will be no need to execute the individual scripts previously listed.

Once you have generated the script to create all the objects, you can execute the script on your new database to recreate the whole schema. This can be done with SSMS or any other tool that lets you execute SQL commands on your new database. First, you have to register your remote database in SSMS (select View

Figure 13-4
Figure 13-5

Figure 13.5. Figure 13-5

Figure 13-6

Figure 13.6. Figure 13-6

Figure 13-7

Figure 13.7. Figure 13-7

Importing Existing Data

The script we created and executed created the objects but didn't populate the tables with data. While developing the site on your local computer, you created quite a lot of data to define article categories, forums, polls, products, users, and so on, and you'll want to import all that information into the new database instead of recreating it from scratch. You might think that you could generate a script with INSERT statements for all the records from all your tables and then execute it on the new database. However, neither Visual Studio's Server Explorer nor your local installation of SSMS have the ability to create SQL INSERT scripts for your data, and you may end up coding the statements manually. If you only need to script a few dozen records, writing statements by hand may be feasible, but if you have to generate hundreds or thousands of INSERT statements for any table, then you will want to look at one of the many third-party tools that can automatically generate the script for you.

If you can connect to both the local and remote database by means of SQL Server Management Studio (SSMS), things are much easier. When you use the tool's Import Data feature, it allows you to choose all tables, but you can't select the order in which they will be imported, and you'll get many import errors if the tool tries to insert data into a detail table that has a foreign key to a master table for which the data hasn't been imported yet. To solve the problem, you need to temporarily disable the referential integrity checks during the import, so that the tool can insert data into a table even if the records reference other records that are not present in the master table yet. To do this, you use the ALTER TABLE <tablename> NOCHECK CONSTRAINT ALL statement for every table, as follows:

ALTER TABLE tbh_Articles NOCHECK CONSTRAINT ALL
ALTER TABLE tbh_Categories NOCHECK CONSTRAINT ALL
ALTER TABLE tbh_Comments NOCHECK CONSTRAINT ALL
...do the same for all other tables required by ASP.NET and your application

After disabling constraints, select the target database in which you want to import the data (this may be a local database or a database on the remote server) in the Object Explorer, and select Tasks

Importing Existing Data
Figure 13-8

Figure 13.8. Figure 13-8

In the first wizard step, you select the source database, which will be the TheBeerHouse database attached to the .MDF SQL Server Express file (see Figure 13-9).

Figure 13-9

Figure 13.9. Figure 13-9

In the second step you choose the destination database, which will already be selected. If you're targeting a remote database (not on your own computer), you probably also need to modify the options to choose SQL Server Authentication, and enter your credentials to connect to it. In the next step, you select all the tables you want to import, which will be all tables starting with aspnet_ and tbh_ (see Figure 13-10).

Figure 13-10

Figure 13.10. Figure 13-10

You could omit the following tables if you prefer: sysdiagrams and aspnet_WebEventEvents. Also, make sure you do not select the objects beginning with vw_aspnet, as these are views that don't contain their own data in reality. Before proceeding to the next step, you must go into the import options of each selected table, by clicking the Edit button on the right side of the grid listing the objects. Select the Enable Identity Insert option (see Figure 13-11) to ensure that records are imported with their original identity values (for columns such as ApplicationID, CategoryID, ArticleID, PollID, etc.). This is necessary so that inserted rows will respect the referential integrity (other tables have foreign keys that reference the specific values in these identity columns, so we have to insert the original values instead of letting it assign new values). You might think it's a good idea to select Delete Rows in Destination Table so that you won't get duplicate key errors if you're re-importing the data. This won't work, however, because it will try to use truncate statements that don't work on any table that has foreign keys (even if the constraints are off). So you need to use a script to delete all rows first if you want to re-import data, rather than use this checkbox.

Complete the wizard and check the box that lets you save the SSIS package, and check File System. When you see the Package Protection dialog, select "Encrypt all data with password" and specify a password. Select a filename for this package and run the actual process; it will import all rows as specified. Save the SSIS package in a file so that you can easily rerun this import in the future without having to do all the setup steps again (just double-click on that file). However, be careful because you have to empty your tables before doing this and you don't want to do this once you have real users in a production environment! Figure 13-12 shows the screen providing feedback about the process.

Figure 13-11

Figure 13.11. Figure 13-11

Figure 13-12

Figure 13.12. Figure 13-12

The last thing to do is reenable the constraints you previously disabled, by running the following statements on the remote database, from a query window:

ALTER TABLE tbh_Articles CHECK CONSTRAINT ALL
ALTER TABLE tbh_Categories CHECK CONSTRAINT ALL
ALTER TABLE tbh_Comments CHECK CONSTRAINT ALL
...do the same for all other tables required by ASP.NET and custom features

The entire import takes a couple of minutes to complete, and you end up with a perfect replication of the local SQL Server database.

When you're done, remember to detach the original SQL Server Express .MDF file used as a source; otherwise, you will no longer be able to open it from Visual Studio and run the site against it. This is not a concern if you used a full edition of SQL Server on your development computer.

Deploying the Site

There are three main methods to deploy the site's files:

  • You can simply copy all files to the remote hosting space, including .aspx and .ascx files, .vb/.cs source code files, etc. Visual Studio includes a tool that allows you to copy the web project's file to another directory on the local machine, to a UNC path, to an IIS virtual application, or to a remote FTP site. This is the simplest option, but it's sometimes not desirable because your source code files will be copied as is, in "clear-text" format on the server, and many developers don't like this. As long as you deploy the site on your own in-house server that's fine, of course, but as soon as you need to deploy on a shared hosting space you'll probably want to precompile the source code so that you protect it (at least a bit, as it can always be decompiled if someone really wants to see your code) from prying eyes.

    Even if your source code files are deployed to the server, they still cannot be downloaded by users because of the IIS settings, but it's probably best not to have them on the server at all.

  • In addition to precompiling the site's source code files (the .vb or .cs files), you can also precompile the files containing the markup code (such as .aspx and .ascx files). Then, you'll only deploy the compiler-generated .dll assemblies, plus the .aspx/.ascx files as usual. However, because you precompiled the markup files, their content was stripped out by the compilation process, and they now only contain a placeholder string. For the actual deployment you can use an FTP client to copy the precompiled files to the server. In addition to offering better protection of your code, you're also making it harder for anyone to change your site's UI: this is particularly important if you sell the site as a packaged product and you put copyright notices and logos on the pages, and you don't want your client to remove or change them. Another advantage is that your code won't have to be compiled the first time a user accesses the site (but there will still be a JIT compile to go from IL to native code), which leads to slightly better performance the first time your site is accessed after deployment, or after IIS recycles the application.

    You can generate an installer program that takes care of the complete setup of the web application, including extracting the site's files from CAB files, copying them to a folder selected by the user, creating a virtual directory/IIS application on the destination server, executing SQL scripts to create and prefill the database, and more. This option is particularly attractive to those of you who are developing a site that will be sold as a packaged application. In that case, it's standard to give users an installer program that takes care of the application's setup as much as possible. Note, however, that this approach isn't always useful because the user must have administrative rights on the destination server to install the site, and he needs to launch your installer program directly on the server itself. Therefore, this is not viable if you're targeting a shared hosting space. You can, however, create the installer anyway, so that clients will have the option to use it if they decide to deploy the site to their own server, or they can use FTP to deploy the site to a shared hosting service. The following sections explore these options in more detail.

Copying the Site Locally or Remotely

One of the problems that developers need to be aware of when developing websites with Visual Studio is that the built-in web server is not equivalent to IIS. It's normally very good, but you need to be aware that your website may function differently in some ways when deployed to a real IIS server. For this reason, you should always deploy your site to IIS and test it before deploying it to a production server. To demonstrate the Visual Studio Copy Website built-in tool, I'll show you how to copy the site to an IIS application, so that you can test the site on a real web server. Only professional and server versions of Windows have IIS, and even then it's not installed by default. If you have a home version of Windows, you'll have to deploy to a different system that has IIS installed. First, create a virtual folder/IIS application from the IIS Administration console, as shown in Figure 13-13.

Figure 13-13

Figure 13.13. Figure 13-13

Ensure that ASP.NET version 2.0 is selected in the Edit Application Pool dialog: IIS 7.0 only offers the 2.0 framework by default. ASP.NET 3.5 uses the .NET 2.0 CLR, so there is no ASP.NET 3.5 version available in IIS. Also note the Managed Pipeline Mode is set to Integrated as opposed to Classic. IIS 7.0 adds a new processing model known as integrated. In integrated mode HttpModules are executed as part of IIS and not the website directly. This does not mean that all custom HttpModules, such as the URL Rewrite module you created in Chapter 3, have to be executed at the server level. For more detailed information about IIS 7, I recommend Professional IIS, ISBN: 978-0-470-09782-3, www.wiley.com/WileyCDA/WileyTitle/productCd-0470097825.html.

Once the website has been created in IIS, it can be copied directly from Visual Studio, click the Copy Website item from the IDE's Web Site menu. First you must connect to the destination, which can be a normal folder, an IIS/HTTP site, or an FTP site. In Figure Figure 13-14, I'm connecting to the TheBeerHouse application folder (created previously) on my local IIS server.

Figure 13-14

Figure 13.14. Figure 13-14

The tool's user interface is simple: once you select the destination, you can choose to copy everything from the source (the local copy of the site's files) to the destination, to copy everything from the destination back to the source (useful when someone else has updated the site and you want to download the latest version to your computer), or to synchronize the files on the source and destination according to their date. To deploy all your files, including source code, first make sure that your web.config file has the connection string for your remote database. Then, connect to your remote site on the right side and select everything on the left, except for the App_Data folder, and copy it to the right side. Figure 13-15 shows the tool after a successful complete copy.

Figure 13-15

Figure 13.15. Figure 13-15

Although you can choose an FTP site as the destination for the copy, Visual Studio's Copy Web Site feature is slower than most third-party FTP clients, and it hung a few times while I was testing this feature. Therefore I prefer using an external FTP client instead of the Copy Web Site feature when I am deploying to a remote site using FTP. Personally, I like the freeware FileZilla FTP client (http://filezilla.sourceforge.net/). However, the Copy Web Site feature works well when copying to a local folder or an IIS application.

It is a good idea to hide the updating process from site visitors because as the files are being updated the application will most likely not respond and will throw numerous exceptions until the update process is complete. This has been a problem since applications have been on the web. When ASP.NET 2.0 was released, there was a feature added called app_offline.htm. Whenever this file is present in the site's root directory it is displayed in response to any request. This gives you the opportunity to put up a sign about the site being temporarily closed, without any ugly errors occurring. As soon as this file is removed or renamed, the normal application execution resumes.

Precompiling the Site

If you deploy the site by copying all the files (including the source code), the pages and the source code files are compiled dynamically at runtime when they are first requested by a user. This is called in-place compilation, and the generated assemblies are compiled into a temporary folder. As an alternative, instead of deploying source files, you can use the aspnet_compiler.exe tool (located under C:WINDOWSMicrosoft.NETFrameworkv2.0.50727) to precompile the source code files and (optionally) the markup files. This is the command you could use to precompile everything (this should all be entered on one line):

aspnet_compiler.exe -p c:ProjectsASP.NETTheBeerHouseTBH_Web
-v /TheBeerHouse c:DeploymentTheBeerHouse

The -p parameter specifies the source directory, and the -v parameter specifies the virtual directory used at runtime by the site. The path at the end of the command is the destination directory for the compiler output files. If you look under the c:DeploymentTheBeerHousein folder, you'll find multiple .dll assembly files, plus one .compiled XML file for each .aspx and .ascx file (see Figure 13-16).

Figure 13-16

Figure 13.16. Figure 13-16

The files named with a .compiled extension contain XML text that shows the relationship between the virtual path of a page or user control and the corresponding type compiled into one of the assemblies. If you look into any of the .aspx files, you won't find any HTML/ASPX markup code, but rather the following markup string:

This is a marker file generated by the precompilation tool,
and should not be deleted!

After executing the aspnet_compiler, you take all the output generated by this tool and upload it to the remote server, typically via FTP. If you're deploying to a server within your network you might simply copy the files to a shared folder on that server. However, even local servers are often isolated behind a firewall, so FTP may be needed anyway.

Compiling the markup code may definitely be appealing in some circumstances, such as for packaged commercial products for which you don't want the client to change anything; however, if you're deploying to your own site, this may not be particularly useful or necessary. Furthermore, it would complicate updates, because every time you needed to change a line of markup you'd have to recompile everything and redeploy the generated files. In the case of deploying to your own sites, it's simpler to precompile only the source code files but not the markup files. To do this, just add the -u switch (which stands for updateable) to the command line, as follows:

aspnet_compiler.exe -p c:ProjectsASP.NETTheBeerHouseTBH_Web
-v /TheBeerHouse -u c:DeploymentTheBeerHouse

With this command no .compiled files will be generated under the /bin folder, and the content of the .aspx and .ascx files won't be removed. However, the CodeFile attribute of the @Page and @Control directives will be removed, and the Inherits will be updated with a reference to the type compiled into one of the generated assemblies.

Note

All static files (images, .htm files, .css stylesheet files, etc.) are always copied "as is" to the target folder. These are never included as part of a precompile.

However, there's a small deployment issue when using one of the two precompile commands described previously: the assemblies they generate always have a different name, which makes it difficult to update the site locally and then replicate the changes remotely, because the assembly names will be different after each precompile. If you don't want to leave old and unused assemblies in the remote /bin folder, you need to delete them first and then upload all new .dll files. This is very annoying and time-consuming, so you can add the -fixednames compiler switch to cause the aspnet_compiler to create an assembly for each file it compiles, using a fixed name scheme. This is good because it allows you to update the site locally, recompile it, and then upload only the changed assembly file. This is the modified command line:

aspnet_compiler.exe -p c:ProjectsASP.NETTheBeerHouseTBH_Web
-v /TheBeerHouse -u -fixednames c:DeploymentTheBeerHouse

I covered the syntax of the command-line tool for completeness (and because many of you will want to script this procedure), but you don't have to remember all the various switches because Visual Studio provides a simple integrated UI for aspnet_compiler, which you can access by clicking Build

Figure 13-16
Figure 13-17

Figure 13.17. Figure 13-17

Some of you may be concerned about the large quantity of assemblies produced by the precompilation step. In large projects with hundreds of pages, the /bin folder will contain a lot of files, and it may be more convenient for deployment if you could combine all those .dll files into a single assembly file. This is done with a tool called asp_merge.exe. You can read more detail about the tool at http://msdn.microsoft.com/en-us/library/bb397866.aspx. It is located under the C:Program FilesMicrosoft SDKsWindowsv6.0ABin folder. As its name suggests, it enables you to merge the multiple assemblies generated by the aspnet_compiler tool into a single dll. When you run this program you only need to specify the path of the precompiled website where it can find the assemblies you want to merge:

aspnet_merge.exe c:DeploymentTheBeerHouse

The preceding command generates a dll for each of the website's folders containing files that were precompiled by aspnet_compiler. This is useful when you have folders that include a subapplication supported by different developers (such as the administration console), and you want to have separate assemblies for separate sections so that you can update them independently on the production server. In other cases, however, you may prefer to merge everything into a single assembly; you can do so with the -o switch, which specifies the name of the assembly being generated:

aspnet_merge.exe c:DeploymentTheBeerHouse -o TheBeerHouse.dll

Note

The tool can be used whether aspnet_compiler.exe precompiled the markup code or not. But the tool never merges in any external libraries referenced by the website's source files and pages, such as the FredCK.FCKEditorV2.dll assemblies. It only merges assemblies generated by aspnet_compiler.exe.

Using the Visual Studio Web Deployment Projects

As for aspnet_compiler, there's also a front end UI for aspnet_merge. The Visual Studio Web Deployment Projects package, www.microsoft.com/downloads/details.aspx?FamilyId=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&displaylang=en, is installed as an add-in for VS, and it adds a new project type called a "Deployment Project." You add a new deployment project to your solution by clicking the Add Web Deployment Project option on the IDE's Build menu or via the same option on the context menu of the website in the Solution Explorer window. You create the project by choosing its name and location from the dialog box shown in Figure 13-18.

Figure 13-18

Figure 13.18. Figure 13-18

The project added to the Solution Explorer contains no files; you have to double-click the project name to open its configuration dialog box, from which you can specify a number of options. Among other things, you can specify how you want the precompiler to work, and how you want the files merged. In the first field of the dialog box (see Figure 13-19), you specify the output folder and choose whether the user interface pages and controls should be precompiled (which is the updatable option, corresponding to the -u switch of the aspnet_compiler.exe tool).

Figure 13-19

Figure 13.19. Figure 13-19

In the second tab, Output Assemblies (see Figure 13-20), you specify whether you want to compile everything into a single assembly, have an assembly for each folder, have an assembly for the user interface pages and controls, or have an assembly for each class and page being compiled (this last option means you don't want to use aspnet_merge.exe). From here, you can also specify the version information of the generated assemblies. If this information is not provided, the settings specified in the web.config file located under the /App_code folder will be used instead (if the file is present, which is not a requirement).

Figure 13-20

Figure 13.20. Figure 13-20

The third tab, Signing, enables you to sign the generated assemblies with a key file generated by the sn.exe command-line tool, to give them a strong name. This isn't normally desired for your own sites, but may be useful when you're creating a packaged application and you want to ensure that your assemblies will not be tampered with. In the last tab, Deployment (see Figure 13-21), you can choose to replace one or more sections of the site's web.config file with the content from another file. For example, if you write connectionStrings=productionConnectionStrings.config, the whole <connectionStrings> section will be replaced with the content of the ProductionConnectionStrings.config file at the end of the build process. This enables you to have a connection string pointing the SQL Server Express database to be used while testing the site locally, and later have it automatically replaced with a connection string referencing a local or remote SQL Server database after building the project for deployment. You can specify additional sections to replace, one per line. You can also use this window to specify a virtual directory to be created during the build process, and whether the App_Data folder will be deleted from the files generated (useful when you will use a SQL Server database after the build, in which case you do not want to deploy your express files under App_Data ).

Figure 13-21

Figure 13.21. Figure 13-21

Once you've completed the configuration, you can build the project. At the end of the build process, you'll find a copy of the site with the precompiled and merged assemblies, plus all other files such as pages, controls, images, stylesheets, and so on in the output folder. You can then take this entire output and upload everything to the production server, typically via FTP.

Deployment projects simply consist of an XML file used to pass options to MSBuild.exe, the new Microsoft build tool capable of compiling and building complex projects and solutions. MSBuild is an extensible tool that uses configuration files that can contain many different options. And if an option or a task that you'd like doesn't exist yet, you can create it as a class and have MSBuild call it. Many of the configuration settings described here were implemented as custom settings and tasks by the developers of the Web Deployment Projects add-in. There are many more available options in addition to those you can configure from the Properties window explored earlier, such as the option to exclude files from the build, create new folders, grant the ASP.NET account write access to a folder (only on your local machine, though — you'll still need to replicate these security settings on the remote production server), execute external programs, and much more. You can add more settings and tasks (i.e., operations to run before or after the build and the merge processes) directly from the XML configuration file, which can be opened by clicking the Open Project File option from the Web Deployment project's context menu. Covering MSBuild is beyond the scope of this book, but you can find a lot of good documentation about this on the web and in the documents that come with the Web Deployment Projects package.

Note

By default, all projects added to the solution are built in Visual Studio when you launch the primary project, that is, the website. Building the deployment project takes quite a lot of time, however, depending on the size of the site (on my machine it takes around 30 seconds to generate the precompiled site), and it is not something you want to do while testing the site locally. In order to avoid this waste of time, you can just exclude the project from the Debug Build from the Build

Figure 13-21

Creating an Installer for a Packaged Application

Creating an installer package that you can give to your clients, and that completely installs and sets up your site automatically, may be simpler than you think. In the old days, the setup programs were typically created with tools such as InstallShield or Wise Installation System, but starting with VS.NET 2003 they can be created with VS itself, thanks to the Web Setup Project types you find by selecting Other Project Types

Creating an Installer for a Packaged Application
Figure 13-22

Figure 13.22. Figure 13-22

The Web Setup Project is tailor-made for creating installers for web-based applications. You add one such project to your current solution, and then you must tell it which files you want to include in the package. You could choose files one by one, but there may be thousands of files (including images and all static content files), so instead you can add the output of another project to the package (see Figure 13-23), and, in particular, the output of the Web Deployment project created earlier (see Figure 13-24). This includes everything you need (pages, controls, precompiled assemblies, and static content), so you shouldn't need to add anything else. If you do, however, then you could still add individual files from other sources — for example, if you wanted to include a manual that isn't among the website's deployment-related files.

Figure 13-23

Figure 13.23. Figure 13-23

Figure 13-24

Figure 13.24. Figure 13-24

After you create the project, it preconfigures the creation of a Web Folder in the File System editor, as the destination for the installation process (see Figure 13-25). You can change its default name, the default page, application mappings, and related options that you would have manually configured from the virtual directory's Properties window in the IIS Administration console.

Figure 13-25

Figure 13.25. Figure 13-25

The default user interface includes steps for choosing the destination server and the folder name, and default options for the execution of the installation process. You can, however, open the User Interface editor (click the sixth icon from the left in Server Explorer's toolbar, after ensuring that the Setup project is selected) and add, remove, or modify steps. For example, you can put an image banner on them to customize their default appearance. Or, as shown in Figure 13-26, you can add a step that shows a license file, which users must agree to before proceeding.

After you've configured everything, you can build the project, and you'll end up with a setup.exe file that launches an .MSI file. Figure 13-27 shows the installer at runtime, demonstrating the step where you choose the destination server and folder, and the classic progress bar.

Creating a setup program in a matter of minutes is very cool! This basic setup does quite a lot of things (it creates a destination folder, turns it into an IIS virtual application with the proper settings, and copies all the necessary files into it), but it could be further extended with custom steps and actions. For example, you could create an additional step that enables users to choose whether they want to use a SQL Server Express database or a SQL Server database, and in the latter case it could execute .SQL scripts to automatically create the database and the required objects. Covering these advanced topics is beyond the scope of this book, as it pertains to the Installer projects and desktop programming in general, but I wanted you to know that you can create some useful setup programs using only Visual Studio. However, in some situations where you have advanced needs, there is still some benefit to be obtained from third-party installation builders such as InstallShield and Wise.

Figure 13-26

Figure 13.26. Figure 13-26

Figure 13-27

Figure 13.27. Figure 13-27

Solution

The "Solution" section of this chapter was actually merged with the "Design" section when I demonstrated how to solve the deployment problems while discussing some of the ASP.NET features, and I provided the background knowledge necessary to deploy the site. The solution I actually implemented for deploying the sample site consisted of using a Web Deployment Project to create a local precompiled copy of the site in an IIS virtual application, which I later deployed to the production server by means of an FTP client. I also switched from using SQL Server Express on my development computer to using the full SQL Server as my deployed target. To see my result, you can browse the sample site online by going to www.beerhouse.extremewebworks.com. I also created a web installer so that I could easily redistribute the site to colleagues, friends, and other people.

Summary

In this chapter, you've looked at all the options for deploying an ASP.NET 3.5 site, either on a local IIS server or to a remote production site. The new ASP.NET compilation model enables you to use a simple XCOPY deployment that includes everything but lacks protection of source code and takes a little time to compile upon the first page request. If that's a problem for you, you can use the command-line tools and the Visual Studio wizards to precompile the site and generate one or more assemblies to deploy. Different options for different needs; this new model is very flexible, and everyone will find something they like! This brings us to the end of our journey. I hope you like what you have read, and I wish you happy coding!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset