Professional ASP.NET 1.0 Special Edition- P21 doc

40 90 0
Professional ASP.NET 1.0 Special Edition- P21 doc

Đ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

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 Import directive. 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  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 DirectorySearcher. The directives for global.asax are straightforward to use. Later, in the Advanced Topics section, we will take a deeper look at one of these directives. For now, let's turn our focus to the code we can write within global.asax. Code Declaration Code is declared in global.asax using <Script runat="server"/> blocks. These are identical to the script blocks defined in ASP.NET pages, so we won't explain their syntax in detail again. 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 File and 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 Virtual option, 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.  Declarative object tags - <Object> tags enable us to declare and instantiate Application and Session objects 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.asax file, let's take a quick diversion and discuss application state management before moving on to the supported application 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" ' 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 Session data 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. 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; 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 sessionValue = Session("SimpleSession") and in C#: string sessionValue; sessionValue = Session["SimpleSession"]; For types other than String, the semantics of accessing the value stored in Session are a bit more explicit. Since Session stores its data as an Object type, giving it the flexibility to store any .NET item, when we wish to retrieve data (other than type String) we have to cast the return value to the correct type. 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: Note that for a class instance to be stored in out-of-process Session state, the class must be marked with the [Serializable] attribute. Dim po As PurchaseOrder po = CType(Session("po"), PurchaseOrder) and in C#: PurchaseOrder po; po = (PurchaseOrder) Session["po"]; 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). 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") 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() Application("HitCount") = 0 End Sub Public Sub Application_OnBeginRequest() Application.Lock() Application("HitCounter") = Application("HitCounter") + 1 Application.UnLock() End Sub and now in C#: public void Application_OnStart() { [...]... 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: What if we didn't need to monitor a file, but instead wanted to remove... 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: Professional ASP.NET 2nd Edition 1861007035... XslTransform() ' Do we have the Wrox Pro ASP.NET 2nd Ed book in the Cache? If (IsNothing(Cache("1861007035.xml"))) Then CacheStatus.Text = "Item not present, updating the Cache " UpdateCache("1861007035.xml") Else CacheStatus.Text = "Retrieving from Cache" End If ' Load the transform xsl.Load(Server.MapPath("book.xsl")) dom = CType(Cache("1861007035.xml"), XmlDocument) BookDisplay.Document = dom BookDisplay.Transform... ' Create a CacheDependency on this key Dim dependency as New CacheDependency(nothing, dependencyKey) ' Cache the XML document Cache.Insert("1861007035.xml", Load("1861007035.xml"), dependency) Status() End Sub Private Function Load(xmlFile As String) As XmlDocument Dim dom As New XmlDocument() dom.Load(Server.MapPath(xmlFile)) Return dom End Function Public Sub Invalidate(sender As Object, e As EventArgs)... HTTP module is an advanced feature of ASP.NET It is the equivalent of IIS's ISAPI filter concept An HTTP module gives us an opportunity to work with the request before it is serviced by an ASP.NET page or web service (or custom HTTP Handler), and again, before the response is sent to the client For example, we can use HTTP modules to author custom solutions for our ASP.NET applications, such as an authentication... applications, such as an authentication system that authenticates users against a Netscape LDAP ASP.NET application events are multi-cast events This means that we can have both an HTTP module and global.asax respond to the same event ASP.NET supports 18 application events, and also allows us to add our own custom events ASP.NET also introduces support for asynchronous events We will discuss these at the end... Application_OnAuthenticateRequest - This event is raised when ASP.NET is ready to perform authentication on the request (see Chapter 14 for more detail on authentication) Events such as this allow us to easily build in custom authentication systems to ASP.NET Within this event, we can examine the request and execute our own code to determine whether or not the request is authenticated When enabled, ASP.NET authentication modes such... raised when ASP.NET is ready to authorize a request for a resource We can use this event to examine the request and execute our own code that determines what privileges we grant or deny the request Similar to the previous event, when enabled, the ASP.NET authorization system relies on this event for its authorization support Application_OnResolveRequestCache - Although not yet discussed, ASP.NET has... future requests This event is raised when ASP.NET is ready to determine if the request should be served from the Cache Internally, ASP.NET' s output cache relies upon this event We can use it to run application code independently of whether or not the actual response is served from the output cache Application_OnAcquireRequestState - This event is raised when ASP.NET is ready to acquire Session state... example, an ISP running ASP.NET could use the Application_OnEndRequest event to add a footer to the bottom of all pages served by ASP.NET Here is the global.asax code in Visual Basic NET: Public Sub Application_OnEndRequest(sender As Object, e As EventArgs) Response.Write("") Response.Write("This page was " _ & "served by ASP.NET") End . we open the 18 6 10 0 703 5.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. file: <?xml version=" ;1. 0& quot;?> <books> <book> <name> ;Professional ASP. NET 2nd Edition</name> <isbn> ;18 6 10 0 703 5</isbn> <publisher>Wrox. EventArgs) Dim dom As XmlDocument Dim xsl As New XslTransform() ' Do we have the Wrox Pro ASP. NET 2nd Ed book in the Cache? If (IsNothing(Cache(" ;18 6 10 0 703 5.xml"))) Then

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

Tài liệu cùng người dùng

Tài liệu liên quan