Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]
.pdf
648 C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T
Set up Windows account permissions for the worker process user: The user under which the worker process (either aspnet_wp.exe or w3wp.exe in IIS 6.0) needs access to the application directories (at least read if the application doesn’t write anything to these directories). If your application accesses other resources such as the registry or event log, you have to configure the permission for the worker process account to access these resources.
Add IIS file mappings: Add IIS file mappings if you want to process any URLs with filename extensions that are different from the extensions registered on a default ASP.NET installation.
Configure ASP.NET through the web.config file for production environments: In other words, add (or modify) any connection strings and application settings as well as security and authorization settings, session state settings, and globalization settings appropriately.
In some cases it is also required to modify machine.config: For example, if you are in a web hosting environment and your application runs on multiple web servers for load balancing, you have to synchronize any encryption keys used for encrypting forms authentication tickets or view state on all those machines. These keys are stored in machine.config and need to be equal on every machine in the web farm so that one machine is able to decrypt information encrypted by another machine that previously processed the request.
Definitely when it comes to deployment, you should know about a couple of useful things. First, before running ASP.NET applications the first time on a server, it might be useful to verify whether ASP.NET has been installed appropriately. Then you have to decide which version of ASP.NET your application requires. Actually, as with every other .NET Framework application, you can run as many ASP.NET runtimes side by side as you want. And of course don’t forget to turn off the debug configuration option in the <compilation> section of web.config.
<configuration>
<system.web>
<!-- Other settings omitted. -->
<compilation defaultLanguage="cs" debug="false" /> </system.web>
<configuration>
When debugging is enabled, the compiled ASP.NET web-page code will be larger and execute more slowly. Additionally, temporary compilation files won’t be deleted automatically. For that reason, debugging should be used only while testing your web application.
Of course, you don’t need to deploy any project and solution files (*.sln, *.vbproj, *.csproj, and so on) used by Visual Studio. In the case of using precompilation (either the classic one as used in ASP.NET 1.x or the site precompilation based on aspnet_compiler as introduced in the section “Compilation Models” of this chapter), source code files (*.cs, *.vb) and resource files (*.resx) don’t need to be deployed. And of course, as you probably won’t debug on production machines, you don’t need any *.pdb files there as well.
Verifying the ASP.NET Installation
After installing ASP.NET, it’s a good idea to test that it’s working. All you need to do is create a simple ASP.NET page, request it in a browser, and make sure it’s processed successfully.
To perform this test, create a new physical directory on your computer. Now, use the Create Virtual Directory Wizard to expose this directory as a virtual directory named Test. Finally, create a new file in this directory using Notepad. Name this file test.aspx. The filename isn’t that important, but the extension is. It’s the .aspx extension that tells IIS that this file needs to be processed by the ASP.NET engine.
C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T |
649 |
Inside the test.aspx file, paste the following code:
<html>
<body>
<h1>The date is <% Response.Write(DateTime.Now.ToShortDateString()) %> </h1>
</body>
</html>
When you request this file in a browser, ASP.NET will load the file, execute the embedded code statement (which retrieves the current date and inserts it into the page), and then return the final HTML page. This example isn’t a full-fledged ASP.NET web page, because it doesn’t use the web control model you learned about in the first part of this book. However, it’s still enough to test that ASP.NET is working properly. When you enter http://localhost/Test/_test.aspx in the browser, you should see a page that looks like the one shown in Figure 18-21.
Figure 18-21. ASP.NET is correctly installed.
If you see only the plain text, as in Figure 18-22, ASP.NET isn’t installed correctly. This problem commonly occurs if ASP.NET is installed but the ASP.NET file types aren’t registered in IIS. In this case, ASP.NET won’t actually process the request. Instead, the raw page will be sent directly to the user, and the browser will display only the content that isn’t inside a tag or script block.
Figure 18-22. ASP.NET isn’t installed or configured correctly.
You can usually solve this problem by repairing your IIS file mappings using the aspnet_regiis.exe utility described earlier. Here’s the syntax you’ll need:
c:\[WinDir]\Microsoft.NET\Framework\[Version]\aspnet_regiis.exe -i
Microsoft provides more detailed information about troubleshooting and aspnet_regiis.exe in a knowledge-base article at http://support.microsoft.com/_default.aspx?scid=kb;en-us;325093.
652 C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T
Table 18-4. Continued
Setting |
Description |
CompilationTempDirectory |
Specifies the directory used as temporary file storage for |
|
dynamic compilation. |
requestPriority |
Enables you to set priorities for web pages as they are |
|
processed by the ASP.NET runtime. This is interesting if |
|
you want to have a website or a part of a website running |
|
in the same worker process be more responsive than |
|
others. A typical example for that is an administrative |
|
page that has to be responsive in all cases. Sites or parts |
|
of a website configured with the value High will be |
|
processed faster and before lower prioritized parts of |
|
the website by the ASP.NET runtime. |
|
|
Compilation Models
As you already know, ASP.NET comes with a compilation model for dynamically compiling assemblies out of tag-based code and actual source code. The application itself is always executed as a compiled version for increasing performance. Of course, special directories play an important role for dynamic compilation, as explained previously. ASP.NET offers three ways for compiling web applications:
Classic precompilation: ASP.NET introduced this model with its first release. With this compilation model, parts of the website are precompiled (of course, any referenced assemblies as well as the code-behind portions with the page processing logic), and others such as the tagbased code files (ASPX or ASMX files) are dynamically compiled at runtime with the first request. This model can be used only with the classic code-behind model where the actual page inherits from the compiled base class with the page logic.
Dynamic compilation: The application is deployed with all tag and source code files, and ASP.NET completely compiles the application on the fly. The advantage of this approach is that making changes just in tag files or even source code files is possible on the fly, and the application is automatically compiled after a change occurs. Of course, the big disadvantage is that dynamic compilation takes place on the first request, and therefore the first request after a change in code will need more time than subsequent requests (and to be honest, in large production systems we don’t suggest making changes directly in source code without testing them first in test environments). This mechanism has been available since ASP.NET 2.0.
Site precompilation: ASP.NET 2.0 introduces a new model for precompilation that allows compiling the whole website into binaries so that no code files, even tag files such as ASPX or ASMX files, are completely compiled into binaries and deployed as binaries onto the target machine.
When creating a new website project, ASP.NET by default selects the dynamic compilation model. That means all the code and pages are stored as tag and source code files on the file system, and ASP.NET dynamically compiles them. Therefore, the first request will require a little bit more time as ASP.NET compiles the whole page. In that case, it might be better to deploy the site already in a compiled format, which you can do with site precompilation. For site precompilation, you have to use a separate tool for compiling the web application called aspent_compiler.exe. The compiler is stored in the Microsoft .NET Framework directory. The compiler has to be launched on your test/development machine before you deploy the entire website. Basically, the tool takes the following parameters:
C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T |
653 |
aspnet_compiler -m metabase path
-v virtual directory path -p physical path
target directory
Therefore, you can specify either a metabase path, the virtual path, or the file system path for the application to be compiled as well as a target directory for the application. In Figure 18-24 you can see the aspnet_compiler.exe tool in action.
Figure 18-24. The aspnet_compiler.exe tool in action
As you can see, the compiler creates several files in the target directory. But when taking a closer look at the Default.aspx file, you’ll recognize that it doesn’t contain any useful tags; it just contains the information “This is a marker file generated by the precompilation tool, and should not be deleted!” All the actual code and tags are compiled into the binaries located in the Bin directory. Now you can just copy the resulting directory structure to the target machine and share the directory as virtual directory, and the application is ready to run.
Deploying with Visual Studio
Visual Studio offers an option for directly deploying websites from within the development environment onto a web server. This option supports multiple protocols such as FTP and FrontPage Server Extensions. Selecting Copy Web Site from the Web Site menu from within Visual Studio opens the dialog box shown in Figure 18-25.
The dialog box shows you the website on the left side and the remote machine on the right side. For connecting to a remote machine, just click the button next to the Connect To drop-down list. This fires up another dialog box, as shown in Figure 18-26, for selecting the target website. As you can see, besides to a local directory or local IIS instance, remote sites can be accessed either through FTP or FrontPage Server Extensions.
C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T |
655 |
After connecting to the server, you can select files and directories from the left panel (which displays the content of your project) and move them over to the previously selected server. Of course, in the case of FTP or FrontPage Server Extensions, the website must already be configured on the remote machine.
The VirtualPathProvider in ASP.NET 2.0
The VirtualPathProvider class is a special part of the basic ASP.NET framework. It allows you to implement some sort of “virtual URL” accessible on the server. This gives you the possibility of generating a response for a URL dynamically without having an ASPX or HTML file stored on the hard disk.
Why is that interesting, and why will you learn about that in this chapter? Well, the VirtualPathProvider class gives you the additional possibility of deploying your web application (or, rather, parts of your web application). Actually, you have the possibility of storing “pages” of the web application somewhere else than on the file system without writing your own basic page framework that uses information in the database for dynamically creating controls and adding them to the page. You just can retrieve the whole file from the database and pass it to the ASP.NET runtime for further processing. The runtime treats the information retrieved from the database (or any other data store) like a physical page located on the file system. And that’s not all. You can use the VirtualPathProvider class for accessing other features such as themes and skins from a different location than the file system. With such a possibility you can write fully customizable applications by providing some management system that allows you to upload new themes and skins into a database (perhaps on a per-user or per–user group basis) that are accessed by the runtime through the VirtualPathProvider class you have written.
The best way to understand the possibilities of the VirtualPathProvider class is to walk through a simple example. You will learn how to write a simple VirtualPathProvider class that can read ASPX files from a database table stored in SQL Server.
■Note Of course, the VirtualPathProvider is one possibility for getting “file content” from a location different from the file system. Actually, Windows SharePoint Services use a similar mechanism of retrieving content from somewhere other than the file system. But, on the other hand, this can (but need not to) affect the performance of your application depending on what and how you are reading the data (file) and where the store or database is located in your network. Therefore, always be careful to use them properly and test them with your requirements before actually building a large system based in it. This possibility adds some flexibility for parts of large applications but should not be used for “storing the complete application” in a database instead of the file system.
Let’s get started with the simple example. You will need a database table on your local SQL Server that looks like the one shown in Figure 18-27.
As you can see, the table includes a filename (which is the primary key as well) and the actual content. The content can be any type of code ASP.NET understands. Because you are serving just simple pages in the sample, the content can be anything the page parser is able to compile. After that, you can create a new website. Of course, both—files stored physically on the file system and files stored virtually in the database—should be accessible. You have to take that into consideration when writing your own implementation for the VirtualPathProvider class.
656 C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T
Figure 18-27. The SQL Server database used for the VirtualPathProvider
Therefore, when creating a new website, you just leave the Default.aspx page in place and modify its code as follows:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default_aspx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<title>Untitled Page</title> </head>
<body>
<form id="form1" runat="server"> <div>
<b>This is the physical page</b><br />
Served last time at <%= DateTime.Now.ToString() %> </div>
</form>
</body>
</html>
C H A P T E R 1 8 ■ W E B S I T E D E P L OY M E N T |
657 |
Next, you have to create your implementation of the VirtualPathProvider class. The VirtualPathProvider class is defined in the System.Web.Hosting namespace. Just add a new class to the app_code directory and inherit from VirtualPathProvider. The class needs to implement at least the following methods:
public class MyProvider : System.Web.Hosting.VirtualPathProvider
{
public static void Appinitialize()
{
MyProvider fileProvider = new MyProvider(); System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(
fileProvider);
}
public override bool FileExists(string virtualPath)
{
throw new Exception("The method or operation is not implemented.");
}
public override System.Web.Hosting.VirtualFile GetFile(string virtualPath)
{
throw new Exception("The method or operation is not implemented.");
}
}
In addition, the VirtualPathProvider class has functions for verifying a directory (DirectoryExists) and getting file hashes (GetFileHash) as well as cache verification (GetCacheDependency) that should be overridden for more complex solutions. Furthermore, currently it requires you to implement a static method called AppInitialize. If the method is present in a VirtualPathProvider class, it is automatically called by the framework. Within this method, you create an instance of your own provider and register it for the hosting environment. If you don’t do that, the framework simply won’t know about your virtual provider and therefore will not use it at all.
As you can see in the previous code snippet, the GetFile method needs to return a virtual file. This virtual file is then used by the ASP.NET hosting framework for opening the file. Therefore, it provides an Open method. The Open method needs to return the contents for the entry in your database, but how will the content for your database get there? The VirtualFile class itself doesn’t accept any parameters except the virtual path of the file. And—not really surprisingly—it is abstract.
So, the solution is simple—you have to create your own implementation of VirtualFile and override the Open method. This method then returns a stream to the ASP.NET infrastructure, which actually returns the contents of your database file. The following is the implementation of the simple VirtualFile class:
public class MyVirtualFile : System.Web.Hosting.VirtualFile
{
private string _FileContent;
public MyVirtualFile(string virtualPath, string fileContent) : base(virtualPath)
{
_FileContent = fileContent;
}
public override Stream Open()
{
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream, Encoding.Unicode);
