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

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

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

188 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

response.Write("<html><body>");

// Get the name of the requested file. string file = request.QueryString["file"]; try

{

// Open the file and display its contents one line at a time. response.Write("<b>Listing " + file + "</b><br />"); StreamReader r = File.OpenText(

server.MapPath(Path.Combine("./", file))); string line = "";

while (line != null)

{

line = r.ReadLine();

if (line != null)

{

//Make sure tags and other special characters are

//replaced by their corresponding HTML entities so that

//they can be displayed appropriately.

line = server.HtmlEncode(line);

//Replace spaces and tabs with nonbreaking spaces

//to preserve whitespace.

line = line.Replace(" ", " "); line = line.Replace(

"\t", "     ");

//A more sophisticated source viewer might apply

//color coding.

response.Write(line + "<br />");

}

}

r.Close();

}

catch (Exception err)

{

response.Write(err.Message);

}

response.Write("</html></body>");

}

public bool IsReusable

{

get {return true;}

}

}

}

This code simply finds the requested file, reads its content, and uses a little string substitution (for example, replacing spaces with nonbreaking spaces and line breaks with the <br /> element) and HTML encoding to create a representation that can be safely displayed in a browser. You’ll learn more about techniques for reading and manipulating files in Chapter 13.

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

189

Next, you can map the handler to a file extension, as follows:

<httpHandlers>

<add verb="*" path="source.simple" type="HttpExtensions.SourceHandler,HttpExtensions"/>

</httpHandlers>

To test this handler, you can use a URL in this format:

http://localhost:[Port]/Chapter05/source.simple?file=HolmesQuote.aspx.cs

The HTTP handler will then show the source code for the .cs file, as shown in Figure 5-14.

Figure 5-14. Using a more sophisticated HTTP handler

Based on this example, you can probably imagine a variety of different ways you can use HTTP handlers. For example, you could render a custom image, perform an ad hoc database query, or return some binary data. These examples extend the ASP.NET architecture but bypass the web-page model. The result is a leaner, more efficient component.

You can also create HTTP handlers that work asynchronously. This means they create a new thread to do their work, instead of using one of the ASP.NET worker threads. This improves scalability in situations where you need to perform a task that takes a long amount of time but isn’t CPU-intensive. A classic example is waiting to read an extremely slow network resource. ASP.NET allows a fixed set of worker threads to run only at one time (typically 25), so once this limit is reached additional requests will be queued, even if the computer has available CPU time.

190 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

HTTP HANDLERS AND SESSION STATE

By default, HTTP handlers do not have access to client-specific session state. That’s because HTTP handlers are generally used for lower-level tasks, and skipping the steps needed to serialize and retrieve session state information achieves a minor increase in performance. However, if you do need access to session state information, you simply need to implement one of the following two interfaces:

IRequiresSessionState

IReadOnlySessionState

If you require just read-only access to session state, you should implement the IRequiresSessionState interface. If you need to modify or add to session information, you should implement the IReadOnlySessionState interface. You should never implement both at the same time.

These two interfaces are just marker interfaces and do not contain any methods. That means you don’t need to write any extra code to enable session support. For example, if you want to use read-only session state with the SimpleHandler class, you would declare it in this way:

public class SimpleHandler : IHttpHandler, IReadOnlySessionState {...}

To actually access the Session object, you’ll need to work through the HttpContext object that’s submitted to the ProcessRequest() method. It provides a Session property.

With asynchronous handlers, additional requests can be accepted, because the handler creates a new thread to process each request rather than using the worker process. Of course, there is a risk with this approach. Namely, if you create too many threads for the computer to manage efficiently, or if you try to do too much CPU-intensive work at once, the performance of the entire web server will be adversely affected. Asynchronous HTTP handlers are beyond the scope of this book, but you can read an excellent introduction from MSDN Magazine at http://msdn.microsoft.com/msdnmag/ issues/03/06/Threading.

Creating a Custom HTTP Module

It’s just as easy to create custom HTTP modules as custom HTTP handlers. You simply need to author a class that implements the System.Web.IHttpModule interface. You can then register your module by adding it to the <httpModules> section of the web.config file. However, you don’t need to configure IIS to use your HTTP modules. That’s because modules are automatically used for every web request.

So, how does an HTTP module plug itself into the ASP.NET request processing pipeline? It does so in the same way as the global.asax file. Essentially, when an HTTP module is created, it registers to receive specific global application events. For example, if the module is concerned with authentication, it will register itself to receive the authentication events. Whenever those events occur, ASP.NET invokes all the interested HTTP modules. The HTTP module wires up its events with delegate code in the Init() method.

The IHttpModule interface defines the two methods shown in Table 5-5.

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

191

Table 5-5. IHttpModule Members

Member

Description

Init()

This method allows an HTTP module to register its event handlers to receive

 

the events of the HttpApplication object. This method provides the current

 

HttpApplication object for the request as a parameter.

Dispose()

This method gives an HTTP module an opportunity to perform any cleanup

 

before the object gets garbage collected.

 

 

The following class is a custom HTTP module that handles the event HttpApplication.AuthenticateRequest and then logs the user information to a new entry in the Windows event log using the EventLog class from the System.Diagnostics namespace. To use this example, the account used to run ASP.NET code must have permission to write to the event log.

using System; using System.Web;

using System.Diagnostics;

namespace HttpExtensions

{

public class LogUserModule : IHttpModule

{

public void Init(HttpApplication httpApp)

{

// Attach application event handlers.

httpApp.AuthenticateRequest += new EventHandler(OnAuthentication);

}

private void OnAuthentication(object sender, EventArgs a)

{

// Get the current user identity.

string name = HttpContext.Current.User.Identity.Name;

// Log the user name. EventLog log = new EventLog();

log.Source = "Log User Module"; log.WriteEntry(name + " was authenticated.");

}

public void Dispose() {}

}

}

Now you can register the module with the following information in the web.config file. Here’s an example that assumes it’s compiled in a separate assembly named HttpExtensions.dll:

<httpModules>

<add name="LogUserModule" type="HttpExtensions.LogUserModule,HttpExtensions" />

</httpModules>

To test this module, request any other page in the web application. Then check the entry in the Windows application event log. (To view the log, select Programs Administrative Tools Event Viewer from the Start menu.) Figure 5-15 shows the logged messages.

192 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

Figure 5-15. Logging messages with an HTTP module

In Part 4, you’ll see a more detailed example that uses an HTTP module to perform custom authentication.

HANDLING EVENTS FROM OTHER MODULES

The previous example shows how you can handle application events in a custom HTTP module. However, some global events aren’t provided by the HttpApplication class but are still quite important. These include events raised by other HTTP modules, such as the events fired to start and end a session.

Fortunately, you can wire up to these events in the Init() event; you just need a slightly different approach. The HttpApplication class provides a collection of all the modules that are a part of the current HTTP pipeline through the Modules collection. You can retrieve a module by name and then use delegate code to connect an event handler.

For example, if you want to connect an event handler named OnSessionStart() to the SessionStateModule.Start event, you could use code like this for the Init() method in your HTTP module:

public void Init(HttpApplication httpApp)

{

SessionStateModule sessionMod = httpApp.Modules["Session"]; sessionMod.Start += new EventHandler(OnSessionStart);

}

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

193

Summary

In this chapter, you took a closer look at what constitutes an ASP.NET application. After learning more about the life cycle of an application, you learned how to code global application event handlers with the global.asax file and how to set application configuration with the web.config file. Finally, you learned how to use separately compiled components in your web pages and how to extend the HTTP pipeline with your own handlers and modules.

C H A P T E R 6

■ ■ ■

State Management

No web application framework, no matter how advanced, can change that HTTP is a stateless protocol. After every web request, the client disconnects from the server, and the ASP.NET engine discards the page objects. This architecture ensures that web applications can scale up to serve thousands of simultaneous requests without running out of server memory. The drawback is that your code needs to use other techniques to store information between web requests and retrieve it when needed.

In this chapter, you’ll see how to tackle this challenge by maintaining information on the server and on the client using a variety of techniques. You’ll also learn how to transfer information from one web page to another.

STATE MANAGEMENT CHANGES IN .NET 2.0

The standbys of state management remain the same in ASP.NET 2.0. That means the programming interface for session state, application state, view state, and the query string hasn’t changed at all. However, session state now offers more configuration options, and there’s a new way to transfer information between pages.

Here’s a preview of the changes:

Cross-page postbacks: In ASP.NET 1.x, a page could post only to itself. In ASP.NET 2.0, you can post from one page to another, transferring the page’s state at the same time.

New session state settings: Session state is now more configurable. You have options that allow you to use a custom SQL Server database (instead of one named ASPState), set timeouts, and configure how cookies are used and named.

Custom session state providers: Microsoft has opened the session state model so that you can develop custom session state providers (and session ID providers) that store state in other data sources or generate session IDs using different algorithms.

Profiles: Rather than coding your own database retrieval logic, you can use the new profile API to store userspecific information in a database. Best of all, this information is strongly typed, unlike session state. Profiles build on the ASP.NET authentication model.

Out of these four topics, you’ll see only the first two in this chapter. Profiles are discussed in Chapter 24, because you need to use them in conjunction with Windows authentication or forms authentication. Custom session state providers are beyond the scope of this book. However, expect to see third-party session providers that allow you to use sessions with other relational databases.

195

196 C H A P T E R 6 S TAT E M A N A G E M E N T

ASP.NET State Management

ASP.NET includes a variety of options for state management. It features the same Session and Application state collections as traditional ASP (with a few enhancements) and an entirely new view state model. ASP.NET even includes a caching system that allows you to retain information without sacrificing server scalability. Each state management choice has a different lifetime, scope, performance overhead, and level of support.

Table 6-1, Table 6-2, and Table 6-3 show an at-a-glance comparison of your state management options.

Table 6-1. State Management Options Compared (Part 1)

 

View State

Query String

Custom Cookies

Allowed Data Types

All serializable .NET

A limited amount

String data.

 

data types.

of string data.

 

Storage Location

A hidden field in the

The browser’s

The client’s

 

current web page.

URL string.

computer (in

 

 

 

memory or a

 

 

 

small text file,

 

 

 

depending on its

 

 

 

lifetime settings).

Lifetime

Retained permanently

Lost when the user

Set by the

 

for postbacks to a

enters a new URL

programmer. It

 

single page.

or closes the browser.

can be used in

 

 

However, can be

multiple pages

 

 

stored in a bookmark.

and can persist

 

 

 

between visits.

Scope

Limited to the current

Limited to the target

The whole

 

page.

page.

ASP.NET

 

 

 

application.

Security

By default it’s insecure,

Clearly visible and easy

Insecure and can

 

although you can use

for the user to modify.

be modified by

 

Page directives to enforce

 

the user.

 

encryption and hashing.

 

 

Performance

Storing a large amount

None, because the

None, because the

Implications

of information will slow

amount of data is

amount of data is

 

transmission but will not

trivial.

trivial.

 

affect server performance.

 

 

Typical Use

Page-specific settings.

Sending a product ID

Personalization

 

 

from a catalog page to

preferences for a

 

 

a details page.

website.

 

 

 

 

Table 6-2. State Management Options Compared (Part 2)

 

Session State

Application State

Allowed Data Types

All serializable .NET data types.

All .NET data types.

 

Nonserializable types are

 

 

supported if you are using

 

 

the default in-process state

 

 

service.

 

Storage Location

Server memory.

Server memory.

C H A P T E R 6 S TAT E M A N A G E M E N T

197

Session State

Application State

Lifetime

Times out after a predefined

 

period (usually 20 minutes

 

but can be altered globally

 

or programmatically).

The lifetime of the application (typically, until the server is rebooted).

Scope

The whole ASP.NET application.

The whole ASP.NET application.

 

 

Unlike most other types of

 

 

methods, application data is

 

 

global to all users.

Security

Secure, because data is never

 

transmitted to the client.

 

However, subject to session

 

hijacking if you don’t use SSL.

Performance

Storing a large amount of

Implications

information can slow down

 

the server severely, especially

 

if there are a large number of

 

users at once, because each

 

user will have a separate copy

 

of session data.

Typical Use

Store items in a shopping

 

basket.

Very secure, because data is never transmitted to the client.

Storing a large amount of information can slow down the server, because this data will never time out and be removed.

Storing any type of global data.

Table 6-3. State Management Options Compared (Part 3)

 

Profiles

Caching

Allowed Data Types

All serializable .NET data types.

All .NET data types.

 

Nonserializable types are

 

 

supported if you create a

 

 

custom profile.

 

Storage Location

A back-end database.

Lifetime

Permanent.

Scope

The whole ASP.NET application.

 

May also be accessed by other

 

applications.

Security

Fairly secure, because although

 

data is never transmitted, it is

 

stored in a database that could

 

be compromised.

Performance

Large amounts of data can be

Implications

stored easily, but there may

 

be a nontrivial overhead in

 

retrieving and writing the

 

data for each request.

Typical Use

Store customer account

 

information.

Server memory.

Depends on the expiration policy you set but may possibly be released early if server memory becomes scarce.

The same as application state (global to all users and all pages).

Very secure, because data is never transmitted to the client.

Storing a large amount of information may force out other, more useful cached information. However, ASP.NET has the ability to remove items early to ensure optimum performance.

Storing data retrieved from a database.