Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
92
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

148 C H A P T E R 4 S E R V E R C O N T R O L S

The event-handling code for this example simply configures a HyperLink control so that it corresponds with the randomly selected advertisement in the AdRotator:

protected void Ads_AdCreated(Object sender, AdCreatedEventArgs e)

{

//Synchronize the Hyperlink control. lnkBanner.NavigateUrl = e.NavigateUrl;

//Synchronize the text of the link.

lnkBanner.Text = "Click here for information about our sponsor: "; lnkBanner.Text += e.AlternateText;

}

The Calendar Control

This control creates a functionally rich and good-looking calendar box that shows one month at a time. The user can move from month to month, select a date, and even select a range of days (if multiple selection is allowed). The Calendar control has many properties that, taken together, allow you to change almost every part of this control. For example, you can fine-tune the foreground and background colors, the font, the title, the format of the date, the currently selected date, and so on. The Calendar also provides events that enable you to react when the user changes the current month (VisibleMonthChanged), when the user selects a date (SelectionChanged), and when the Calendar is about to render a day (DayRender).

The following Calendar tag sets a few basic properties:

<asp:Calendar runat="server" ID="Calendar1" ForeColor="red" BackColor="lightyellow" />

The most important Calendar event is SelectionChanged, which fires every time a user clicks a date. Here’s a basic event handler that responds to the SelectionChanged event and displays the selected date:

protected void Calendar1_SelectionChanged(object sender, EventArgs e)

{

lblDates.Text = "You selected" + Calendar1.SelectedDate.ToLondDateString());

}

Note Every user interaction with the calendar triggers a postback. This allows you to react to the selection event immediately, and it allows the Calendar to rerender its interface, thereby showing a new month or newly selected dates. The Calendar does not use the AutoPostBack property.

You can also allow users to select entire weeks or months as well as single dates, or you can render the control as a static calendar that doesn’t allow selection. The only fact you must remember is that if you allow month selection, the user can also select a single week or a day. Similarly, if you allow week selection, the user can also select a single day. The type of selection is set through the Calendar.SelectionMode property. You may also need to set the Calendar.FirstDayOfWeek property to configure how a week is selected. (For example, if you set FirstDayOfWeek to the enumerated value Monday, weeks will be selected from Monday to Sunday.)

When you allow multiple date selection (by setting Calendar.SelectionMode to something other than Day), you need to examine the SelectedDates property instead of the SelectedDate property. SelectedDates provides a collection of all the selected dates, which you can examine, as shown here:

C H A P T E R 4 S E R V E R C O N T R O L S

149

protected void Calendar1_SelectionChanged(object sender, EventArgs e)

{

lblDates.Text = "You selected these dates:<br />"; foreach (DateTime dt in Calendar1.SelectedDates)

{

lblDates.Text += dt.ToLongDateString() + "<br />";

}

}

The Calendar control exposes many more formatting-related properties, many of which map to the underlying HTML table representation (such as CellSpacing, CellPadding, Caption, and CaptionAlign). Additionally, you can individually tweak portions of the controls through grouped formatting settings called styles (which expose color, font, and alignment options). Example properties include DayHeaderStyle, DayStyle, NextPrevStyle, OtherMonthDayStyle, SelectedDayStyle, TitleStyle, TodayStyle, and WeekendDayStyle. You can change the subproperties for all of these styles using the Properties window.

Finally, by handling the DayRender event, you can completely change the appearance of the cell being rendered. The DayRender event is extremely powerful. Besides allowing you to tailor what dates are selectable, it also allows you to configure the cell where the date is located through the e.Cell property. (The Calendar control is really a sophisticated HTML table.) For example, you could highlight an important date or even add extra controls or HTML content in the cell. Here’s an example that changes the background and foreground colors of the weekend days and also makes them nonclickable so that the user can’t choose those days:

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)

{

if (e.Day.IsWeekend)

{

e.Cell.BackColor = System.Drawing.Color.Green; e.Cell.ForeColor = System.Drawing.Color.Yellow; e.Day.IsSelectable = false;

}

}

Figure 4-16 shows the result.

Figure 4-16. The Calendar control

150C H A P T E R 4 S E R V E R C O N T R O L S

Tip If you’re using a design tool such as Visual Studio, you can even set an entire related color scheme using the built-in designer. Simply select the Auto Format link in the smart tag. You’ll be presented with a list of predefined formats that set various style properties.

Summary

In this chapter you learned the basics of the core server controls included with ASP.NET, such as HTML server controls, web controls, list controls, validation controls, and rich controls. You also learned how to use ASP.NET controls from your web-page code, access their properties, and handle their server-side events. Finally, you learned how to validate potentially problematic user input with the validation controls. In the next chapter, you’ll learn how pages come together to form web applications.

C H A P T E R 5

■ ■ ■

ASP.NET Applications

In traditional desktop programming, an application is an executable file with related support files. For example, a typical Windows application consists of a main executable file (EXE), supporting components (typically DLLs), and other resources such as databases and configuration files. An ASP.NET application follows a much different model.

On the most fundamental level, an ASP.NET application is a combination of files, pages, handlers, modules, and executable code that can be invoked from a virtual directory (and its subdirectories) on a web server. In this chapter, you’ll learn why this distinction exists and take a closer look at how an ASP.NET application is configured and deployed. You’ll also learn how to use components and HTTP handlers with an ASP.NET application.

WEB APPLICATION CHANGES IN .NET 2.0

The web application model remains essentially the same in ASP.NET 2.0. The most significant change is the improvement in the configuration model, which now boasts a programmable API and a graphical web-page interface.

Here are the changes you’ll see, in the order they appear in this chapter:

Application directory structure: ASP.NET 1.x had one special web application directory—the Bin directory, which houses compiled assemblies. ASP.NET 2.0 adds several more for source code, localizable resources, browser definitions, themes, and more.

Configuration API: You can now use a handy set of classes to read and write almost any information in a configuration file.

WAT: The new website administration tool uses the new configuration API to present an easy-to-use webpage interface for configuring a web application.

Encryptable configuration sections: Configuration files often contain sensitive data. Now you can protect them by encrypting any section.

If you’re a seasoned ASP.NET 1.x developer, you can focus on these additions as you work your way through this chapter.

151

152 C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

Anatomy of an ASP.NET Application

The difference between ASP.NET applications and rich client applications makes a lot of sense when you consider the ASP.NET execution model. Unlike a Windows application, the end user never runs an ASP.NET application directly. Instead, a user launches a browser such as Internet Explorer and requests a specific URL (such as http://www.mysite.com/mypage.aspx) over HTTP. This request is received by a web server. When you’re debugging the application in Visual Studio, you use a localonly test server. When you deploy the application, you use the IIS web server, as described in Chapter 18.

The web server has no concept of separate applications—it simply passes the request to the ASP.NET worker process. However, the ASP.NET worker process carefully segregates code execution into different application domains based on the virtual directory. Web pages and web services that are hosted in the same virtual directory (or one of its subdirectories) execute in the same application domain. Web pages and web services in different virtual directories execute in separate application domains.

Note A virtual directory is simply a directory that’s exposed through a web server. In Chapter 18, you’ll learn how to create virtual directories. When using the test server in Visual Studio, your web project directory is treated like a virtual directory. The only exception is that the test server supports only local connections (requests initiated from the current computer).

The Application Domain

An application domain is the .NET equivalent to a process—it’s a boundary enforced by the CLR that ensures that one application can’t influence (or see the in-memory data) of another. The following characteristics are a direct result of the application domain model:

All the web pages and web services in a single web application share the same in-memory resources, such as global application data, per-user session data, and cached data. This information isn’t directly accessible to other ASP.NET or ASP applications.

All the web pages and web services in a single web application share the same core configuration settings. However, you can customize some configuration settings in individual subdirectories of the same virtual directory. For example, you can set only one authentication mechanism for a web application, no matter how many subdirectories it has. However, you can set different authorization rules in each directory to fine-tune who is allowed to access different groups of pages.

All web applications raise global application events at various stages (when the application domain is first created, when it’s destroyed, and so on). You can attach event handlers that react to these global application events using code in the global.asax file in your application’s virtual directory.

In other words, the virtual directory is the basic grouping structure that delimits an ASP.NET application. You can create a legitimate ASP.NET application with a single web page (.aspx file) or web service (.asmx file). However, ASP.NET applications can include all of the following ingredients:

Web pages (.aspx files): These are the cornerstones of any ASP.NET application.

Web services (.asmx files): These allow you to share useful functions with applications on other computers and other platforms.

C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

153

Code-behind files: Depending on the code model you’re using, you may also have separate source code files. If these files are coded in C#, they have the extension .cs.

A configuration file (web.config): This file contains a slew of application-level settings that configure everything from security to debugging and state management.

Global.asax: This file contains event handlers that react to global application events (such as when the application is first being started).

Other components: These are compiled assemblies that contain separate components you’ve developed or third-party components with useful functionality. Components allow you to separate business and data access logic and create custom controls.

Of course, a virtual directory can hold a great deal of additional resources that ASP.NET web applications will use, including stylesheets, images, XML files, and so on. In addition, you can extend the ASP.NET model by developing specialized components known as HTTP handlers and HTTP modules, which can plug into your application and take part in the processing of ASP.NET web requests.

Note It’s possible to have file types that are owned by different ISAPI extensions in the same virtual directory. One example is if you mingle .aspx and .asp files. A more complex example is if you map .aspx web-page files to version 1.1 of ASP.NET and .asmx web service files to version 2.0. In these examples, the virtual directory corresponds to more than one application. These applications just happen to be accessible through the same virtual web directory. However, each application is mediated by a different ISAPI extension.

Application Lifetime

ASP.NET uses a lazy initialization technique for creating application domains. This means that the application domain for a web application is created the first time a request is received for a page or web service in that application.

An application domain can shut down for a variety of reasons, including if the web server itself shuts down. But, more commonly, applications restart themselves in new application domains in response to error conditions or configuration changes. For example, depending on the settings in the computer-wide machine.config file, an ASP.NET application may be periodically recycled when certain thresholds are reached. This model is designed to keep an application healthy and to detect characteristics that could indicate a problem has developed. Depending on your machine.config settings, application domains may be recycled based on the length of time the application domain has been running, the number of queued requests, or the amount of memory used (as described in Chapter 18).

ASP.NET automatically recycles application domains when you change the application. One example is if you modify the web.config file. Another example is if you replace an existing web-page file or DLL assembly file. In both of these cases, ASP.NET starts a new application domain to handle all future requests and keeps the existing application domain alive long enough to finish handling any outstanding requests (including queued requests).

Tip You can programmatically shut down a web application domain using the static HttpRuntime.UnloadAppDomain() method. (The application will restart itself automatically the next time it receives a request.) This technique is rarely used, but it can be useful if you’re hosting a number of web applications on the same server and some are used only infrequently. In this case, the memory overhead of keeping the application domain alive may outweigh the increased speed of serving subsequent requests.

154 C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

Application Updates

One of the most remarkable features about the ASP.NET execution model is that you can update your web application without needing to restart the web server and without worrying about harming existing clients. This means you can add, replace, or delete files in the virtual directory at any time. ASP.NET then performs the same transition to a new application domain that it performs when you modify the web.config configuration file.

Being able to update any part of an application at any time, without interrupting existing requests, is a powerful feature. However, it’s important to understand the architecture that makes it possible. Many developers make the mistake of assuming that it’s a feature of the CLR that allows ASP.NET to seamlessly transition to a new application domain. But in reality, the CLR always locks assembly files when it executes them. To get around this limitation, ASP.NET doesn’t actually use the ASP.NET files in the virtual directory. Instead, it uses another technique, called shadow copy, during the compilation process to create a copy of your files in c:\[WinDir]\Microsoft.NET\[Version]\ Temporary ASP.NET Files. The ASP.NET worker process loads the assemblies from this directory, which means these assemblies are locked.

The second part of the story is ASP.NET’s ability to detect when you change the original files. This detail is fairly straightforward—it simply relies on the ability of the Windows operating system to track directories and files and send immediate change notifications. ASP.NET maintains an active list of all assemblies loaded within a particular application’s application domain and uses monitoring code to watch for changes and acts accordingly.

Note ASP.NET can use files that are stored in the GAC, a computer-wide repository of assemblies that includes staples such as the assemblies for the entire .NET Framework class library. You can also put your own assemblies into the GAC, but web applications are usually simpler to deploy and more straightforward to manage if you don’t.

Application Directory Structure

Every web application should have a well-planned directory structure. Independently from the directory structure you design, ASP.NET defines a few directories with special meanings.

ASP.NET 1.x just introduced one special directory—the Bin directory. ASP.NET 2.0 introduces a few more, as described in Table 5-1.

Table 5-1. Special ASP.NET Directories

Directory

Description

Bin

Contains all the precompiled .NET assemblies (usually DLLs) that

 

the ASP.NET web application uses. These assemblies can include

 

precompiled web-page and web service classes, as well as other

 

assemblies referenced by these classes.

App_Code

Contains source code files that are dynamically compiled for use in

 

your application. These code files are usually separate components,

 

such as a logging component or a data access library. The compiled

 

code never appears in the Bin directory, as ASP.NET places it in the

 

temporary directories used for dynamic compilation.

App_GlobalResources

This directory stores global resources that are accessible to every page

 

in the web application. Chapter 17 has more about resources and

 

localization.

C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

155

Directory

Description

App_LocalResources

This directory serves the same purpose as App_GlobalResources,

 

except these resources are accessible for their dedicated page only.

 

Chapter 17 has more about resources and localization.

App_WebReferences

Stores references to web services that the web application uses. This

 

includes WSDL files and discovery documents. You’ll learn about web

 

services in Part 6.

App_Data

This directory is reserved for data storage, including SQL Server 2005

 

Express database files and XML files. Of course, you’re free to store data

 

files in other directories.

App_Browsers

This directory contains browser definitions stored in XML files. These

 

XML files define the capabilities of client-side browsers for different

 

rendering actions. Although ASP.NET does this globally (across the

 

entire computer), the App_Browsers folder allows you to configure

 

this behavior for separate web applications. See Chapter 27 for more

 

information about how ASP.NET determines different browsers.

App_Themes

Stores the themes used by the web application. You’ll learn more about

 

themes in Chapter 15.

 

 

The global.asax Application File

The global.asax file allows you to write event handlers that react to global events. Users never request the global.asax file directly. Instead, the global.asax file executes its code automatically in response to certain application events. The global.asax file provides a similar service to the global.asa file in classic ASP applications.

You write the code in a global.asax file in a similar way to a web form. The difference is that the global.asax doesn’t contain any HTML or ASP.NET tags. Instead, it contains methods with specific, predefined names. For example, the following global.asax file reacts to the Application.EndRequest event, which happens just before the page is sent to the user:

<script language="C#" runat="server"> protected void Application_OnEndRequest()

{

Response.Write("<hr />This page was served at " + DateTime.Now.ToString());

}

</script>

Although it’s not indicated in the global.asax file, every global.asax file defines the methods for a single class—the application class. The application class derives from HttpApplication, and as a result your code has access to all its public and protected members. This example uses the Response object, which is provided as a built-in property of the HttpApplication class, just like it’s a built-in property of the Page class.

This event handler writes a footer at the bottom of the page with the date and time that the page was created. Because it reacts to the Application.EndRequest event, it executes every time a page is requested after all the event-handling code in that page has finished.

As with web forms, you can also separate the content of the global.asax file into two files, one that declares the file and another that contains the code. However, because there’s no design surface for global.asax files, the division isn’t required. Visual Studio doesn’t give you the option to create a global.asax file with a separate code-behind class.

156 C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

The global.asax file is optional, but a web application can have no more than one global.asax file, and it must reside in the root directory of the application, not in a subdirectory. To add a global.asax file to a project, select Website Add New Item and choose the Global Application Class template. When Visual Studio adds a global.asax file, it includes empty event handlers for the most commonly used application events. You simply need to insert your code in the appropriate method.

It’s worth noting that application event handlers aren’t attached in the same way as ordinary control events. The usual way to attach an application event handler is just to use the recognized method name. For example, if you create a protected method named Application_OnEndRequest(), ASP.NET automatically calls this method when the Application.EndRequest event occurs.

ASP.NET creates a pool of application objects when your application domain is first loaded and uses one to serve each request. This pool varies in size depending on the system and the number of available threads, but it typically ranges from 1 to 100 instances. Each request gets exclusive access to one of these application objects, and when the request ends, the object is reused. As different stages in application processing occur, ASP.NET calls the corresponding method, which triggers your code. Of course, if your methods have the wrong name, your implementation won’t get called—instead, your code will simply be ignored.

Note The global application class that’s used by the global.asax file should always be stateless. That’s because application objects are reused for different requests as they become available. If you set a value in a member variable in one request, it might reappear in another request. However, there’s no way to control how this happens or which request gets which instance of the application object. To circumvent this issue, don’t use member variables unless they’re static (as discussed in Chapter 6).

Application Events

You can handle two types of events in the global.asax file:

Events that always occur for every request. These include request-related and responserelated events.

Events that occur only under certain conditions.

The required events unfold in this order:

1.Application_BeginRequest(): This method is called at the start of every request, including requests for files that aren’t web forms, such as web services.

2.Application_AuthenticateRequest(): This method is called just before authentication is performed. This is a jumping-off point for creating your own authentication logic.

3.Application_AuthorizeRequest(): After the user is authenticated (identified), it’s time to determine the user’s permissions. You can use this method to assign special privileges.

4.Application_ResolveRequestCache(): This method is commonly used in conjunction with output caching. With output caching (described in Chapter 11), the rendered HTML of a web form is reused, without executing any of your code. However, this event handler

still runs.

5.At this point, the request is handed off to the appropriate handler. For example, for a web form request this is the point when the page is compiled (if necessary) and instantiated.

6.Application_AcquireRequestState(): This method is called just before session-specific information is retrieved for the client and used to populate the Session collection.

C H A P T E R 5 A S P. N E T A P P L I C AT I O N S

157

7.Application_PreRequestHandlerExecute(): This method is called before the appropriate HTTP handler executes the request.

8.At this point, the appropriate handler executes the request. For example, if it’s a web form request, the event-handling code for the page is executed, and the page is rendered to HTML.

9.Application_PostRequestHandlerExecute(): This method is called just after the request is handled.

10.Application_ReleaseRequestState(): This method is called when the session-specific information is about to be serialized from the Session collection so that it’s available for the next request.

11.Application_UpdateRequestCache():This method is called just before information is added to the output cache. For example, if you’ve enabled output caching for a web page, ASP.NET will insert the rendered HTML for the page into the cache at this point.

12.Application_EndRequest(): This method is called at the end of the request, just before the objects are released and reclaimed. It’s a suitable point for cleanup code.

Figure 5-1 shows the process of handling a single request.

Figure 5-1. The application events

Some events don’t fire with every request:

Application_Start(): This method is invoked when the application first starts up and the application domain is created. This event handler is a useful place to provide application-wide initialization code. For example, at this point you might load and cache data that will not change throughout the lifetime of an application, such as navigation trees, static product catalogs, and so on.

Session_Start(): This method is invoked each time a new session begins. This is often used to initialize user-specific information. Chapter 6 discusses sessions with state management.