1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 1.0 Special Edition- P21 doc

40 92 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Using Import and Assembly directives in ASP.NET
Định dạng
Số trang 40
Dung lượng 422,64 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

ASP.NET provides four ways to manage state for our application we will cover each in more detail later in the chapter: ƒ User State Session - User state is controlled through the Sessio

Trang 1

in Visual Basic NET or Usingin C# It simply provides a reference to a namespace that contains classes we wish

to make use of

To use the Import directive, we must guarantee that the assembly in which the namespace exists is also available If it

is not, an ASP.NET exception will occur when the application is run Support for adding the assembly is done either through the Assembly directive or the <compilers> section of our configuration file (configuration is covered in the next chapter) To reference assemblies that are not available, we can use the Assembly directive, outlined next

The Import directive requires a single attribute:

ƒ The Namespace attribute of Import is used to identify an assembly namespace for use in global.asax For example, we could use the Import directive specifying the namespace attribute for the System.Data

namespace:<%@ Import namespace="System.Data" %>If we include this directive in the global.asax file for our web application, we can use classes in System.Data without the need to fully qualify the class name For example, if we use the DataSet class, we can refer to it as System.Data.DataSet (fully qualified class name), or use the Import directive naming the System.Data namespace and refer to the class simply as DataSet

Using the Import directive and its Namespace attribute saves us from having to fully qualify the name of the class However, in the event that two namespaces share a common class name (such as Math) we can't use the Importdirective Instead, we would have to fully qualify the names, such as Simple.Math and Complex.Math, when we used them

ƒ Assembly - This directive is used to name assemblies containing classes we wish to use within our ASP.NET application An assembly, which is a compiled unit of code in NET with the extension .dll, exists either in the global assembly cache (covered in Chapter 23) or the bin directory of the ASP.NET application

The Import and Assembly directives are very different Import assumes that the assembly (for example

System.Data.dll) is already available to our application and allows us to use abbreviated class names for classes within that namespace Assembly, on the other hand, is used to tell ASP.NET that there is an assembly that needs to be loaded Remember, assemblies located in the bin directory are automatically loaded

Using the Assembly directive is simple It has one attribute:

ƒ The Name attribute of Assembly identifies the assembly we wish to reference as part of our application As mentioned above, some assemblies are available by default:

ƒ mscorlib.dll - Base classes, such as the definition of Object, String, and so on

ƒ System.dll - Additional base classes, such as the network class libraries

ƒ System.Web.dll - Classes for ASP.NET

ƒ System.Data.dll - Classes for ADO.NET

Trang 2

ƒ System.Web.Services.dll - Classes for ASP.NET web services

ƒ System.Xml.dll - Classes for XML

ƒ System.Drawing.dll - Classes for graphics and drawing

ƒ (Additionally, all assemblies within an application's bin directory)

Included in this list are several System assemblies (for example, the assemblies provided as part of the NET Framework), and those found in application bin directories We would use the Assembly directive when an assembly is registered in the global assembly cache, or when we need System assemblies not already loaded

For example, the assembly System.DirectoryServices.dll contains classes for working with directory services, such as Microsoft's Active Directory This assembly is not one of the default assemblies loaded If we wished to use the classes provided within it in global.asax, we would need to use the Assembly directive:<%@ Assembly

Name="System.DirectoryServices" %>Note that the extension of the assembly (.dll) is not included

We can now write code in our global.asax file that uses classes found within this assembly, such as

Later in the chapter, when we discuss global events, we will implant the events created within these script blocks

There are two additional ways of declaring code in global.asax:

ƒ Server-side includes - global.asax supports the use of server-side #include statements using both Fileand Virtual as the path type to the filename Server-side includes are declared using the following

syntax:<! #Include [File | Virtual]="Path to file" >File identifies the path as being on the file system, while Virtual identifies a virtual directory provided through the web server The contents of the file included will be added to the global.asax file before it is compiled Include files, especially those created using the Virtualoption, can be quite useful as they allow us to define a common directory that can be shared among many applications, which may make our application more portable

If an include file is used within a global.asax, the application will automatically be restarted whenever the include file changes

Trang 3

ƒ Declarative object tags - <Object> tags enable us to declare and instantiate Application and Sessionobjects in global.asax using a declarative tag-based syntax These tags can be used to create NET

assemblies, or COM objects specified by either ProgID or CLSID

The type of object to create is identified using one of three different tag attributes:

ƒ class

ƒ progid

ƒ classid

Only one of these tag attributes can be used per <Object> tag declaration

Using Object Tag Declarations

Here is a sample of how object tag declarations are used:

<object id="appData" runat="server"

class="System.Data.DataSet" scope="Application"/>

We have declared an Application-scoped variable named appData that is of class type System.Data.DataSet However, the object is not actually created until it is first used The object then exists for the lifetime of the context in which it is created In the above example, this is the lifetime of the application Likewise, if the scope were set to Session, the object would be valid for the life of the current user session, and once that session terminated, the object would be destroyed

The attributes used in this declaration are:

Attributes Description

id Unique name to use when referring to the object within the application

runat Must be set to server for the object to execute within ASP.NET

scope Determines where the object lives The choices are Application for application state, Session

for session state, or Appinstance allowing each application to receive its own object instance

[class, progid,

classid] Identifies either the assembly, or the COM ProgID or ClassID to create an instance of

We have three options for adding code to a global.asax file The first, and most common option, will be to use the

<script runat="server"> blocks to define application code We can also define code from an include file and use the

<object/> tag syntax to declaratively create an object Now that we are familiar with how we code our global.asaxfile, let's take a quick diversion and discuss application state management before moving on to the supported application

Trang 4

events

Application State Management

State management is the persistence of objects or values throughout the lifetime of a web application or for the duration

of a user's interaction with the application ASP.NET provides four ways to manage state for our application (we will cover each in more detail later in the chapter):

ƒ User State (Session) - User state is controlled through the Session object Session allows us to maintain data for a limited duration of time (the default is 20 minutes), for a particular user and isolate that data from other users For example, if we wanted to track the ad banners we have shown a particular user, we could do so using Session state If the user doesn't interact with the site within the configurable Session time limit, their data expires and is deleted

ƒ Application State - Application state is controlled through the Application object Application allows us to maintain data for a given ASP.NET application Settings made in Application are accessible to all resources (ASP.NET page, web services, and so on) within our web application For example, if we wanted to retrieve some expensive records out of a database and needed to share this data throughout our application, storing the data

in Application state would be very useful

ƒ Transient Application State (Cache) - Transient Application state is controlled through the Cache object Cache

is similar in functionality to Application, in that it is accessible (shared memory) for our entire web application Cache, however, adds some functionality not available to Application, in the form of dependencies, callbacks, and expiration For example, when our ASP.NET application started we might populate an object used by all ASP.NET pages from an XML file We could store this object in the Cache and could also create a dependency for that item on the XML file the data originated from If the XML file changed, ASP.NET will detect the file change and notify the Cache to invalidate the entry Caching is a very powerful feature of ASP NET We'll summarize the key differences between Application and Cache later in the chapter

ƒ Static Variables - In addition to using Application or Cache to share data within our application, we can also use one of the object-oriented facilities of ASP.NET - static variables We can declare static variables and only one copy of the variable is created no matter how many instances of the class are created The static variable is accessible throughout our application and in some cases is more efficient than Application This is a more advanced option and we will discuss it at the end of the chapter

The use of Application and Session (and now Cache) in ASP.NET is identical to the use of Application and Session in ASP We simply use a string key and set a value:

' Set an Application value

Application("SomeValue") = "my value"

Trang 5

' Read an Application value

Dim someString As String

someString = Application("SomeValue")

These familiar semantics are carried forward and used for the Cache, too:

' Set a Cache value

Cache("SomeValue") = "my value"

' Read a Cache value

Dim someString As String

someString = Cache("SomeValue")

Let's take a deeper look at Session, Application, and Cache and how they relate to building web applications

Session - Managing User State

Classic ASP's familiar Session object is new and improved for ASP.NET The major caveats for Session use in classic ASP are:

ƒ Web farm challenges - Session data is stored in memory on the server it is created upon In a web farm scenario, where there are multiple web servers, a problem could arise if a user was redirected to a server other than the server upon which they stored their Session state Normally, this can be managed by an IP routing solution where the IP address of the client is used to route that client to a particular server However, some ISPs use farms of reverse proxies, and, therefore, the client request may come through a different IP on each request When a user is redirected to a server other than the server that contains their Session data, poorly designed applications can break

ƒ Supporting clients that don't accept HTTP cookies - Since the Web is inherently a stateless environment, to use Session state the client and web server need to share a key that the client can present to identify its Sessiondata on subsequent requests Classic ASP shared this key with the client through the use of an HTTP cookie While this scenario worked well for clients that accept HTTP cookies, it broke for the 1 percent of users that rejected HTTP cookies

Trang 6

Both of these issues have been addressed in ASP.NET's Session state, which supports several new features to remedy these problems:

ƒ Web farm support - ASP.NET Session now supports storing the Session data in-process (in the same memory that ASP.NET uses), out-of-process using Windows NT Service (in separate memory from ASP.NET), and in SQL Server (persistent storage) Both the Windows Service and SQL Server solutions support a web farm scenario where all the web servers can be configured to share a common Session store Thus, as users get routed to different servers each server is able to access that user's Session data To the developer using Session, this

is completely transparent and does not require any changes in the application code Rather, we must configure ASP.NET to support one of these out-of-process options We will discuss configuring Session state in the next chapter

ƒ Cookieless mode - Although somewhat supported in ASP through the use of an ISAPI filter (available as part of the IIS 4.0 SDK), ASP.NET makes cookieless support for Session a first class feature However, by default, Session still uses HTTP cookies When cookieless mode is enabled (details in the next chapter), ASP.NET will munge the URL that it sends back to the client with a Session ID (rather than storing the Session ID in an HTTP cookie) When the client makes a request using the munged URL containing the Session ID, ASP.NET is able to extract it and map the request to the appropriate Session data

We will cover how to configure both of these options in the next chapter when we discuss ASP.NET configuration From our perspective, as a developer coding and using Session, the above features are completely transparent

Programming with Session State

Session is dedicated data storage for each user within an ASP.NET application It is implemented as a Hashtable and stores data based on key/value pair combinations

Setting and Reading Session Value

Use of Session in ASP.NET follows the same usage pattern as classic ASP To set a Session value in Visual Basic NET,

we simply state:

Session("[String key]") = Object

This is the equivalent in C#:

Session["[String key]"] = Object;

Trang 7

We provide Session with a key that identifies the item we are storing This Session stores items of type Object Since all types in NET inherit from Object this allows us to store anything in Session However, objects that contain live references, such as a DataReader containing an open connection to a database, should not be stored in Session

For example, if we wished to store the string Hello World using a key of SimpleSession, we would write the following code in Visual Basic NET:

Session("SimpleSession") = "Hello World"

and in C#:

Session["SimpleSession"] = "Hello World";

Underneath the covers, the CLR knows that the type String originated from type Object, and is then able to store that value correctly in memory

Since Session is available throughout our web application, we can set values in global.asax code and access a

Session value from ASP.NET pages

For example to retrieve our Hello World value from Session, we need only to provide Session with our key for it to return the value This is the Visual Basic NET code:

Dim sessionValue As String

For example, if we stored a custom class we defined called PurchaseOrder in Session, here is how we would need to retrieve it in Visual Basic NET:

Trang 8

Note that for a class instance to be stored in out-of-process Session state, the class must be marked with the

In both examples, we are casting the Object returned by the key po to type PurchaseOrder

The Session API provides additional properties that we can use in code to determine what mode Session is in:

ƒ IsCookieless - Returns True or False indicating whether or not Session is using cookieless mode to maintain the Session ID By default, this is False, meaning that Session is using cookies

ƒ IsReadOnly - Returns True or False indicating whether or not Session is in read-only mode Read-only mode is an optimization that allows ASP.NET to not update Session data This can be particularly useful for outofprocess modes on pages that only read Session state and don't need write access When a Session is read-only, a lock does not have to be maintained and the round-trip back to an out-of-process Session store for

an update can be skipped By default, this value is False, and Session is read/write We will discuss how to enable ReadOnly for Session in the next chapter

ƒ Mode - Returns the value of an enumeration, SessionStateMode, (found in System.Web.SessionState) which indicates the storage mode that Session is configured for Values include InProc, Off, SQLServer, and StateServer

ASP.NET session state is quite different from ASP session state The new capability of session state that is not bound to the ASP.NET process means that developers can begin to use session state in server farm environments without worrying about whether the client is coming through a proxy server Additionally, with the cookieless state functionality, it is even easier to use session state and guarantee that all clients can take advantage of the session state feature In the next chapter, we will learn how we can configure Session to support a read-only mode as well the other 'mode' options (inprocess, Windows Service, and SQL Server)

Trang 9

Application - Managing Application State

Unlike Session, which is basically dedicated storage for each user, Application is shared application storage This shared storage is quite useful, especially if there are resources that all users share, such as an XML representation of a site's shopping catalog Similar to Session, Application state is simply a Hashtable that stores key/value pair combinations

Unlike Session, however, Application does not support the concept of storing data separate from the ASP.NET process Instead, Application stores its data in process with ASP.NET If the ASP.NET process is recycled (covered in the next chapter) Application data is lost The trade-off is that storing the data in-process is faster than going to another process, or possibly across the network, to retrieve data

Setting and Accessing Values

The syntax used for setting and accessing values with Application is identical to that of Session, with one exception

Since Application is accessible in a multi-user environment, updates to Application values should be synchronized This simply means that whenever Application data is being updated, we should prevent other users or applications from updating the data simultaneously Luckily for us, Application provides us with the capability through a simple set

of locking methods Note these are the same locking methods Lock() and UnLock()supported in ASP

Reading and Writing Application Data

We read and write data in Application in a similar manner to Session using key/value pairs, such as the following in Visual Basic NET:

Application("HitCounter") = 10

or in C#:

Application["HitCounter"] = 10;

Similarly, if we wish to read the value back we simply use our key, like this in Visual Basic NET:

Dim HitCount As Integer

HitCount = Application("HitCounter")

Trang 10

or in C#:

int HitCount = Application["HitCounter"];

However, to update HitCounter we must synchronize access using the Lock() and UnLock() methods of

Application Otherwise, the potential exists for two requests to attempt to update HitCounter simultaneously, causing a potential deadlock or update failure

Although this is an illustrative example, when we Lock, we are effectively blocking other applications that may be attempting to update the HitCounter value, causing them to serialize - that is, perform operations one after another.We definitely don't want to Lock/UnLock on each request, as this would negatively affect performance.If the data stored in Application must be updated frequently, it is probably not a good candidate for Application state, unless recreating the data is more costly than the time spent serializing the updates

Let's look at an illustrative example using Application.Lock and Application.UnLock, firstly in Visual Basic NET:

Public Sub Application_OnStart()

Trang 11

When the ASP.NET process is stopped or recycled, Application state is lost However, when the process is recycled, the

Application_OnEnd event (discussed later) is raised and values can be persisted to a database or file

Since ASP.NET is a multi-threaded system, this means that multiple threads can access Application memory simultaneously When we use Application and we wish to set values we must either:

ƒ Know that the object stored in Application is doing its own thread management (not shown) or

ƒ Perform our own synchronization using Application.Lock() and Application.UnLock()

Calling Lock() instructs ASP.NET to block any other threads from modifying this resource until UnLock() is called, giving your code exclusive access However, if we don't explicitly call UnLock(), ASP.NET will call it when the application completes the request, the request times out, or an unhandled error occurs Although this is done for us, we should always aim to write code that explicitly calls UnLock()

Storing Objects in Application

Classic ASP VB objects could not be hosted in Application state due to the default threading model these components supported (Apartment Model threading) In effect, accessing an instance of a VB component stored in Applicationwould cause ASP to serialize (execute one request after another) access to that component .NET components, by default,

Trang 12

are free threaded and don't have this thread affinity problem Thus there are no performance penalties for storing a Visual Basic NET object in Application and accessing it across multiple requests

Next, let's look at a new object, Cache, used to store transient application data

Cache - Managing Transient State

Lots of developers use Application as a cache for frequently used resources For example, reading an XML file that represents a product catalog and storing the object representing that XML file in Application memory

However, what happens when this XML file representing the product catalog changes? In most cases, developers who use Application to manage this data simply force the web application to restart, thus forcing Application to get refreshed

The design goal of the Cache was to give developers the benefits of Application, but with additional features that went above and beyond those provided by Application, such as the ability to evict an item from the Cache when a file changes, it is then our responsibility through code to add the item back to the Cache if we desire

ƒ Lock management - Similar to Application, concurrent requests can attempt to modify the Cache

Application solves this by providing the Lock() and UnLock() methods

Unlike Application though, the Cache class does its own internal lock management Therefore, while Applicationrequired us to explicitly Lock() and UnLock() when updating Application, we don't need to do this with Cache

Keep in mind that we do still need to manage concurrency for objects stored in the Cache just as we do with objects stored in Application

ƒ Resource management - When the Cache detects memory pressure, a least recently used algorithm walks the Cache and automatically evicts items used less frequently Therefore, before we request an item, we always need to check if the item exists

ƒ Callbacks - The Cache supports a capability allowing us to run code when items are removed from the Cache The Cache supports two methods of inserting items:

ƒ Implicit - This is the syntax familiar to us from working with Session or Application using the key/value pairs:

Trang 13

In Visual Basic NET:

Dim productDataSet As New DataSet()

Cache.Insert("products", productDataSet, Nothing)

in Visual Basic NET and in C#:

DataSet productDataSet = new DataSet();

// Populate DataSet

Cache.Insert("products", productDataSet, null)

When using the Cache, we will most likely use the explicit Insert() Let's look at some examples

Dependency-Based Expiration

Trang 14

Dependency-based expiration is very powerful It allows us to create a relationship between an item in the Cache and either a file, another Cache key, or a defined point in time For example, if our site used XML and XSL transforms to control aspects of content we could load the XML into an XmlDocument class and store the value within the Cache We could also establish a relationship between the cached XmlDocument and the file that it is reading, using the file-based dependency feature of the Cache Let's build this sample

Below is the XML file:

<author name="David Sussman"/>

<author name="Brian Francis"/>

<author name="Alex Homer"/>

<author name="Karli Watson"/>

<author name="Rich Anderson"/>

<author name="Rob Howard"/>

</authors>

Trang 15

<description>

ASP.NET is a unified web development

platform that provides the services necessary

for developers to build enterprise-class web

Trang 16

<style>

body { font-family: Arial; font-size: 18; color:white; }

li { list-style: square outside; }

Trang 17

Public Sub Page_Load(sender As Object, e As EventArgs)

Dim dom As XmlDocument

Dim xsl As New XslTransform()

' Do we have the Wrox Pro ASP.NET 2nd Ed book in the Cache?

Trang 18

Public Sub UpdateCache(strItem As String)

Dim strPath As String

Dim dom As New XmlDocument()

' Determine the file path of the file to monitor

strPath = Server.MapPath(strItem)

' Load the file into an Xml Dom

dom.Load(strPath)

' Create a CacheDependency on the file

Dim dependency as New CacheDependency(strPath)

' Cache the XML document

Cache.Insert(strItem, dom, dependency)

Trang 19

End Sub

</Script>

Status: <asp:label id="CacheStatus" runat=server/>

<br>

<asp:xml id="BookDisplay" runat=server/>

The interesting code happens in the UpdateCache subroutine, which is called if the Cache key 1861007035.xml is not

present We first map the path to the XML file, which is in the same directory, and load that XML file into an XmlDocumentclass Then, we create a new CacheDependency class passing in the path to the XML file Finally, we use the Cache's Insert() method and create a new Cache entry using the name of the file (1861007035.xml), the XmlDocumentinstance, dom, and the CacheDependency class instance, dependency

On the first request to this page, we would see:

On subsequent requests we would see a Status of Retrieving from Cache

If we open the 1861007035.xml file and modify the name from Professional ASP.NET 1.0 Special Edition to Pro ASP.NET 1.0, our file change notification would be enforced and the XmlDocument storing the XML from our file would be removed from the Cache Requesting our ASP.NET page would then yield:

Trang 20

What if we didn't need to monitor a file, but instead wanted to remove an entry (or series of entries) from the Cache when another item in the Cache changed? This option is supported through a key-based dependency

The syntax for supporting key-based dependencies is very similar to that for filebased dependencies For example, we can easily change the above code to support a keybased dependency by modifying only a couple of lines

If we cached multiple XML documents for each Wrox book on NET, we could set up a dependency relationship where the Cache entries for the books could be invalidated (and reloaded) whenever a master key, for example

booksDependencyKey, changed

Below is a code example, called KeyBasedvb.aspx, that creates such a relationship:

<%@ Import Namespace="System.Xml" %>

<Script runat="server">

Public Sub Create(sender As Object, e As EventArgs)

' Create the Cache entry for the dependency relationship

' the value of the key doesn't matter

Cache("booksDependencyKey") = "Book Dependency"

' Create a string array with the key names for the

' dependencies to be created upon

Ngày đăng: 03/07/2014, 07:20