Understanding .NET (2nd Edition)

Creating .aspx pages, using controls, defining applications, and exploiting context are fundamental to creating any ASP.NET application. Most applications need more than this, however, including a way to manage state, mechanisms for managing information about their users, and more. The rest of this chapter takes a look at these important areas.

Managing State

Every request a client makes to an ASP.NET application causes the objects on the loaded page to be created, used, and then destroyed. This helps in building scalable applications, since no resources are taken up on the server for clients that aren't currently running requests, and load balancing requests across a group of servers also gets easier. This stateless behavior can also make writing those applications more difficult, however. If all of an application's objects forget everything they've been told after every request, the application won't be very intelligent. To make it easier to create smarter software, ASP.NET provides several different ways for an application to maintain state information between client requests. These options divide into two major categories: storing state on the client and storing state on the server.

Objects in an .aspx page can't maintain their state internally between requests

Storing State on the Client

One way for an ASP.NET application to maintain state between requests from a client is to send that state to the client, then have the client send the state back on its next request. A common way to do this is by using cookies. A cookie is a chunk of information that the ASP.NET application sends to the browser, and it can contain anything: a key for a database lookup, a user identity, or something else. Whatever it is, the user's browser automatically provides the cookie on the next request (unless the user has disabled this function), allowing the application to access and use the information the cookie contains.

State can be sent to a client inside a cookie

It's also possible to store some simple state in a query string, which is text following a "?" at the end of a URL. This information can be expressed as attribute/value pairs, like this:

http://www.qwickbank.com/example.aspx?account=492284 & type=checking

State can be contained in a query string within a URL

Query strings are only useful for small amounts of state, and they're not at all secure. Still, they're the right answer in some situations, and they're quite commonly used.

As already described, the properties in Web controls are automatically saved by inserting their values into the Web pages sent to the user and then reading those values out again when the page is sent back. What actually happens is that this state information is inserted into one or more hidden fields in the page, then read back from those fields when the page is returned. This approach, referred to as view state, offers another way for an application developer to store any other information maintained by a particular page. This mechanism allows an application to store values inside the page sent back to the browser, then have them restored when the user resubmits the page.

Information used by a page can be saved in view state

Storing State on the Server

Storing state on clients is simple, and it's commonly used. Only a relatively small amount of information can be stored, however, and there are other limitations as well. Accordingly, ASP.NET applications often store state on the server.

Information used throughout an application can be saved in the Application object

A limitation of view state, for example, is that it saves information only for a particular page in an ASP.NET application. What if you want to save information used by several pages in the application? To do this, an application can rely on the Application object mentioned earlier. Rather than being sent to the client with each page, information placed in the Application object is maintained on the server and made accessible to all pages in an application. A reference to the Application object from any page in an ASP.NET application will always access the same instance. For example, if an application wishes to record the time at which some event takes place and then let that time be accessed by another page in the same application, it might contain the following line:

<% Application("Timestamp") = Now() %>

A page that wished to access the value of this variable can reference it directly, as in

<% Response.Write (Application("Timestamp")) %>

This book hasn't said much about threading in the .NET Framework, but it's important to note that ASP.NET applications are multithreaded. Since there's only one Application object for an entire ASP.NET application, if two different pages running on two different threads write to it simultaneously, problems can occur. Depending on the threading choices an application uses, explicit concurrency controls might be needed to avoid conflicts.

Alternatively, the Cache object can be used instead of the Application object. As mentioned earlier, the objects are broadly similar in function. The biggest difference is that the Cache object allows much more control over how long information is held and what causes it to be removed. An application can also ask that it be informed when a particular item is deleted from the Cache object, providing an event handler that runs when the information is deleted.

Information used throughout an application can also be stored in the Cache object

Storing state in either of these objects has a problem, however: Both are physically stored on a single machine. If an ASP.NET application is deployed on several Web servers, with client requests load balanced across those servers, storing state in the Application or Cache objects will be problematic. Each copy of the application will have its own instance of these objects, so the information these instances contain will likely be different. Applications that will be load balanced should be careful about how, or even if, they use these objects.

Load balancing complicates state management

The options just described can be useful ways for an application to store state. Yet none of them addresses the most common state management problem in building ASP.NET applications: maintaining per-client state. Think of a Web application that allows its user to add items to a shopping cart, for example. Given that the objects created by the application are destroyed after every request, how can that information be retained? Every page accessed by that client (and only that client) within an ASP.NET application should have easy access to this per-client state, but nothing described so far provides this. Yet building reasonable applications requires some way to store client-specific information across the life of a client session. In ASP.NET, the Session object provides a way to do this.

Information used throughout a single client session can be stored in the Session object

Accessing a Session object looks much like accessing the Application object. To store a value, an .aspx page can contain a line such as

Session("ItemSelected")= 13

To access that value, the page can refer to it like this:

Response.Write(Session("ItemSelected"))

Even though Session and Application objects are accessed in a similar way, don't be confused. There's only one Application object shared by all pages in an ASP.NET application, while every client has its own Session object. When an application accesses the Session object, it will always get the instance associated with the client that made this request. To figure out which client each request comes from, ASP.NET assigns each client a unique session identifier that gets stored in a cookie. The client then presents this cookie with each request it makes, allowing ASP.NET to identify all requests that come from the same client. Because users can turn off cookies if they wish, ASP.NET is also capable of embedding this identifier in the URL string returned to a user. However it's done, the creator of an ASP.NET application doesn't need to worry about determining which request comes from which userit's done for him.

One Session object can exist for each active client

But what about load balancing? Suppose an ASP.NET application's Session object is bound to a particular machine, like the Application object. If this application is load balanced across several different machines, only one of those machines will store this object. Requests from a client that get sent to other machines due to load balancing won't be able to access the object's contents, so they won't execute correctly. While it's possible to use the Session object in this way, only relatively simple applications will adopt this approach.

Using the Session object naively can conflict with load balancing

While the Session object for a particular client can still be stored on just one machine, it can also be stored in a separate Session State Store. If this is done, the contents of the Session object are available to all copies of the application running on all machines in a load-balanced configuration. And because the state is in another process (and perhaps another machine), it can remain available even if the ASP.NET application itself is restarted.

The Session object can work well with load balancing

The standard Session State Store server provided with version 2.0 of the .NET Framework provides five options:

  • InProc: The Session object is stored in the same process as the application. This is the default setting, although for the reasons described earlier, it doesn't work well with load-balancing.

  • StateServer: The Session object's state is stored in another process that can run locally or on another machine.

  • SQLServer: The Session object's state is stored on disk using SQL Server.

  • Custom: The Session object's state is stored in a custom data store, such as an Oracle database.

  • Off: The Session object is disabled.

The Session object can store its state in several different ways

Any state in the Session object is automatically destroyed when a client hasn't accessed the application for a configurable length of time. Note too that how the Session object's state is stored depends entirely on the contents of an application's Web.config file. No code in the application needs to be modified to change which option is used.

Yet another way for an application to store state information on the server, one that's new in ASP.NET 2.0, is using profile properties. Profile properties let an application persistently store information about particular users in an ASP.NET-provided database. Whenever a user accesses the application, her information can be accessed via these properties. Users are identified using one of ASP.NET's login mechanisms, described later, and the association between a user and her properties is made automaticallythe developer isn't required to do any direct database access. The goal is to provide an easy-to-use mechanism for maintaining information about users across multiple accesses.

Information about particular users can be maintained using profile properties

Maintaining state is an important and challenging part of building Web applications. As this short summary has described, ASP.NET provides a number of different ways to do it. Which options make sense for a particular application depends on what the application does and how it's used. Even though it would make life simpler, there's no one-size-fits-all solution for state management.

Caching Data

Clients of an ASP.NET application often access the same information. To make that access faster, it's possible to cache repetitively accessed data. Rather than doing the work required to recreate that data each time it's requested, the information can be read quickly from an in-memory cache and returned. To allow this, ASP.NET provides a way to cache the output of a page. (Don't confuse this with the Cache object described earlier, which is a separate idea.)

Output caching allows saving recently accessed results in memory

To use ASP.NET's output caching mechanism, an .aspx page can contain a directive such as

<%@ OutputCache Duration="60" VaryByParam="none"%>

The duration specifies how long (in seconds) the results of that page can be cached before the information must be recreated. Requests that arrive for the same information within this period will have their responses returned immediately from the cache.

Output caching has several options

The required VaryByParam attribute is set to none in this example, but if desired, it can be used to control exactly which results are cached. The parameter this attribute refers to can be any named value contained in a query string, which is the text following a "?" on a client request. For example, suppose an .aspx page contained the directive

<%@ OutputCache Duration="60" VaryByParam= "name"%>

Suppose further that this page received two requests with these query strings:

http://www.qwickbank.com/page1.aspx?name=Bob http://www.qwickbank.com/page1.aspx?name=Casey

Because output caching was instructed to vary by a parameter called "name," the results of each request would be cached. Requests to this page with names of either Bob or Casey that are received within the 60-second window specified on the Duration attribute will return cached results. Other things, such as the type of browser from which a request originated, can also be used to control exactly which pages are cached. The result is a more responsive application, especially if the same data is accessed over and over.

Authentication and Authorization

Securing Web applications is incredibly important. A plethora of well-publicized attacks have made even nonprofessionals aware of the dangers of too little security. Really understanding Web security is a large topic, one that's outside the scope of this book, but grasping the basics of authentication and authorization is essential.

Browser applications must be secure

Authentication, requiring a user to prove his identity, is a fundamental part of securing an ASP.NET application. Although a developer is free to create her own authentication mechanism, ASP.NET applications have several built-in authentication options provided for them. The choices, which build on what IIS provides, include the following:

  • Windows authentication: Reflecting the IIS choices, there are three options. Basic authentication, simplest of the three, requires a client to send an unencrypted password across the network, which by itself is no one's idea of good security. Digest authentication, the second choice, requires a client to send a hashed version of a password and other information, which provides somewhat better security. The third option, called Integrated Windows Authentication, allows using the authentication protocol available in a Windows domain, such as Kerberos. This choice is quite secure, but it's available only for authenticating users in a Windows domain.

  • Forms authentication: This option allows an application to display a custom form to acquire user credentials, such as a login name and password, and then to decide whether the user is who he claims to be. It relies on the Secure Sockets Layer (SSL) protocol to ensure that those credentials are encrypted when initially sent across the network.

  • Passport authentication: Allows using Microsoft's Internet-based Passport service. System.Web.Security contains several classes that allow applications to access Passport and then use the authenticated client identity it provides.

ASP.NET provides several options for authenticating users

Once a client has been authenticated, the next step is to make an authorization decision, i.e., to determine whether that client is allowed to do what it's requesting. If one of the Windows authentication options is used, a client's attempt to access a particular file such as an .aspx file will be subject to file authorization. This means that Windows will automatically check the access control list (ACL) on the file to ensure that the user's request is allowed. With Windows authentication or any of the other authentication options, an approach called URL authorization is also available. This option allows fine-grained control over who is allowed to perform what operations against a particular ASP.NET application.

ASP.NET applications can make an authorization decision in different ways

Managing Users: Membership

Many Web applications require users to log in before accessing some or all of what the application provides. Knowing who a user is lets the application provide specific services, such as remembering the user's mailing address, and it can also enforce various business relationships, such as payment of a subscription fee. Doing this requires a way to maintain information about the site's users, commonly called membership information, and a mechanism for logging in that uses that information. Version 2.0 of ASP.NET adds support for both of these.

Web applications often keep information about their users

ASP.NET's membership support allows creating and storing information about users, including names, passwords, and more. This information can be stored in SQL Server (the default) or some other data store, although the details of data access are hidden from the developer. Instead, a Membership class is provided that exposes methods such as CreateUser, DeleteUser, FindUsersByName, GeneratePassword, and more. An ASP.NET application can use these methods to perform typical membership operations without dealing explicitly with the underlying data store.

ASP.NET's membership facility allows storing and managing information about an application's users

ASP.NET's membership support can be used together with the forms authentication described earlier, an approach that lets the developer specify in detail exactly what the login process looks like. ASP.NET also includes a set of login controls to help implement membership-based authentication. By default, these controls use the ASP.NET membership system. For example, the CreateUserWizard control collects information from a user such as her user name, password, and e-mail address, then creates an account in the ASP.NET membership system for her. Once this is done, the Login control can be used to let a user log in to an account maintained by the membership system. Other controls are also available, such as a ChangePassword control and a PasswordRecovery control that can let a user have her password sent to whatever e-mail address is registered for her account. To secure the interaction with the user's browser, the login controls can be configured to use SSL.

ASP.NET includes Web controls for creating and managing user login

Perspective: Packing More Into the System

Providing built-in support for doing common things can make creating applications significantly easier. The designers of ASP.NET 2.0 believe strongly in this approach, as exemplified by the addition of membership facilities and login controls. What were once extras are now a standard part of the platform.

In fact, this approach is a fundamental aspect of Microsoft's business model. ASP.NET and the entire .NET Framework are part of Windows, which means they come at no extra charge. Compare this to competing application platforms, such as Java application servers, where all but the open source options carry four- and five-figure price tags. As Microsoft packs more and more into ASP.NET and the other parts of the .NET Framework, they're increasing the value these technologies provide to customers. The company still gets revenue for these things, of course, but it's part of the price that customers pay for Windows. In future releases, we should expect to see features that we now pay extra for, such as some parts of the integration-oriented BizTalk Server, move into Windows itself. Commoditizing technology appears to be a primary goal for Microsoft.

Working with Data: Data Binding

ASP.NET provides Web controls to simplify working with data

ASP.NET applications frequently need to access data in a database, a file, or someplace else. Like any .NET Framework application, ASP.NET applications can use ADO.NET, System.XML, or other mechanisms to do this. Yet for some very common requirements, such as displaying data to a user and allowing him to update it, using these relatively low-level technologies can entail a significant amount of work. To make these common problems easier to solve, ASP.NET 2.0 includes a set of Web controls for working with data (controls that differ significantly from those in earlier releases). Their goal is to make it as simple as possible to implement the most common things that ASP.NET applications do with data.

Data binding allows accessing diverse data and displaying it in various ways

The idea of directly connecting what's displayed by a control with data that lives outside that control, such as data in a database, is referred to as data binding. Doing this requires solving two distinct problems: accessing the data, which might be stored in diverse ways, and displaying that data, again in diverse ways. For example, the data an application uses might be contained in SQL Server or some other database, or in an XML file, or someplace else. Similarly, the application might wish to display that data in a table, a list, or some other fashion. Both problems must be addressed for a complete solution, but they're quite distinct. Accordingly, the Web controls provided by ASP.NET for data binding are divided into two categories: data source controls, which know how to access data, and data-bound controls, which know how to display data. Figure 5-6 shows how these two kinds of controls relate to one another.

Figure 5-6. Data-bound controls display data that's accessed via data source controls.

As the figure illustrates, data source controls connect to actual sources of data. Several different data source controls are provided, each capable of connecting to a particular type of data source. The SqlDataSource control uses ADO.NET to connect to a database, for example, such as SQL Server or Oracle, while the XmlDataSource control knows how to access and work with information stored in an XML file. ASP.NET applications can also use business logic implemented in a middle tier, and so the ObjectDataSource control is capable of connecting to data contained in objects within this logic. Other data source controls are also provided, and a developer can create her own if necessary.

Data source controls know how to access data

What's New in ASP.NET 2.0

As is probably obvious by now, version 2.0 of ASP.NET adds a good deal to this technology. The most important new additions, including support for membership, revamped data binding, and Web Parts, are described in the text. Quite a few other things were also added that are worth mentioning. They include:

  • The ability to add on-screen navigation of a Web site using a site-map file and the new TreeView and SiteMapPath controls. It's also possible to automatically display the position of the current page in the page hierarchy using a format like Home > Accounts > Balances. Sometimes called a breadcrumb, the goal is to help users navigate the site more effectively.

  • A way to define a master page for an application, then have the standard format of that page automatically applied to all pages in this application. A similar concept called themes can also be used to give pages and controls a consistent look.

  • An option to precompile applications, which avoids the performance hit caused by compiling pages when they're first accessed. This option can also be used to remove all source code from an ASP.NET application, which helps protect the intellectual property of its creators.

  • Better tools for managing a Web site created using ASP.NET.

It's fair to say that, of all the changes in version 2.0 of the .NET Framework, the most significant are in ASP.NET. And given the wide use of this technology, these changes are certainly the ones that will affect the most developers.

Once data has found its way into a data source control, it can be accessed by any data-bound control. Each data-bound control knows how to render data in a browser using an appropriate HTML format. The DataList control, for example, is capable of displaying data in a customizable table, while the DetailsView control allows examining and updating individual records. Various list controls, such as ListBox, DropDownList, and BulletedList, allow displaying data in the variety of list styles that user interfaces commonly employ, and the GridView control, new in ASP.NET 2.0, provides a powerful way to examine and modify data in a grid format.

Data-bound controls know how to display data

The goal of all of this technology is to make life as simple as possible for ASP.NET developers who build applications that work with data. Rather than writing detailed code to access, display, and update information, a programmer can just configure the appropriate controls. ASP.NET 2.0 introduced significant changes in this area, and the result should be increased developer productivity.

ASP.NET 2.0 changes how data binding is done

Customizing User Interfaces: Web Parts

People like to be in charge. Even with the potentially mundane, such as how an application looks in a Web browser, giving users the ability to customize things makes people happy. Web Parts, a new addition in ASP.NET 2.0, makes this possible. By allowing users to modify the appearance and behavior of a Web page, add new controls, and more, Web Parts let those users change an application's interface to suit them.

Web Parts allow creating user-customizable interfaces

Interface customization relies on Web Parts controls

ASP.NET Web Parts is actually just a set of controls. A page that uses these controls can contain one or more zones, each of which can contain one or more Web Parts controls. These controls expose actions to a user, such as the ability to change the content the control displays or change the control's position on the screen. Users can also change the pages themselves, including adding new columns with specific Web Parts controls, changing the page's color, and more. This kind of interface customization is commonly referred to as personalization.

Standard Web Parts controls are provided for various functions

As usual with ASP.NET, applications that use Web Parts can be created using Visual Studio 2005. Like any other control, a Web Parts control can be dragged and dropped onto a page, then customized as needed. More advanced developers can create their own Web Parts controls, all of which inherit from the System.Web.UI.WebControls.WebParts.WebPart class. Wherever the controls come from, a page will always contain one WebPartManager control that's responsible for coordinating the activity of all other Web Parts controls on this page. A page will also commonly contain controls such as CatalogZone, which allows presenting users with a list of Web Parts controls that can be added to this page, and EditorZone, which lets users modify a page's Web Parts controls.

The Role of Windows SharePoint Services

Portal is surely one of the most poorly defined words in software today. To most people, it suggests a way to access information through a common Web-based interface. Microsoft provides a more specific meaning with Windows SharePoint Services, a standard part of the Windows Server operating system. Built on ASP.NET, this technology (commonly called just SharePoint) allows creating portal sites that help people collaborate. Microsoft also provides a large set of SharePoint application templates to quickly create sites for employee timesheets and scheduling, expense reimbursement, room reservations, and other purposes.

A key part of a portal is the ability to customize the user interface. Accordingly, SharePoint includes Web Parts much like those in ASP.NET 2.0. Yet ASP.NET and SharePoint are quite different. The goal of ASP.NET is to help developers build all kinds of Web applications, using various data sources and allowing access by all kinds of users. The goal of SharePoint, by contrast, is to make it possible for IT professionals to quickly assemble, deploy, and manage portal applications. Given these distinct goals, the two technologies differ in significant ways. For example, while ASP.NET focuses on the developers who create Web applications, SharePoint also offers options to help administrators deploy and administer sites over a number of machines. ASP.NET takes a more general approach in other ways as well, letting developers choose how to store data, identify users, and more. SharePoint relies on SQL Server for storage, Active Directory for accessing user information, and other standard parts of the Windows environment. While there is some overlap in the two technologies, they nonetheless solve different problems.

ASP.NET Web Parts also includes its own mechanism for persistently storing the changes a user makes. This allows someone to access the application, modify their interface in any way they like, then have this modified interface presented when they next use this application. This storage mechanism is entirely separate from the profile properties described earlier, as it's intended to be used only by Web Parts controls.

Changes a user makes via Web Parts can be stored persistently

The Web Parts technology is a useful addition to ASP.NET. By letting developers create portal-like applications, it expands the range of problems that the .NET Framework can address. As always, this expansion increases the complexity for developers, but for applications that need it, the capability is essential.

Web Parts allow building a wider range of Web applications

Категории