Professional ASP.NET 1.0 Special Edition- P32 pps

40 192 0
Professional ASP.NET 1.0 Special Edition- P32 pps

Đ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

instead of the original component. When we execute the modified page, displayProducts_ovr.aspx, we can see that the new value for average price is now displayed. We will also add some code to display the newest product: Transactions in .NET To provide integration with COM+, the CLR provides the same declarative transaction model. This allows managed objects to participate in existing transactions. We can use these transactions from within ASP.NET pages, and also from within .NET components. At the ASP.NET page level you can add a page-level directive for this: <%@ Page Transaction="Required" %> The allowable values are: Value Description Disabled Transactional context will be ignored. This is the default. NotSupported The page does not run within a transaction. The object context is created without a transaction. Supported The page runs within the scope of an existing transaction, if one is active. If no transaction scope is active, the page runs without a transaction. Required The page runs within the scope of a transaction, either an existing one, or creating one if no existing transaction exists. RequiresNew The page requires a new transaction, and one will be created for each page request. To participate in the transaction success or failure, you can either rely on transaction AutoComplete or explicitly commit or abort the transaction. With AutoComplete enabled, your page will vote to commit the transaction if the page runs without throwing an exception. AutoComplete is enabled by default on a page, so if the page completes successfully, then the page will vote to commit. You can also explicitly control the transaction result by calling the methods of the ContextUtil class. To vote to abort a transaction, you call: ContextUtil.SetAbort() And, if you want to vote to commit a transaction, you call: ContextUtil.SetComplete() For components, we need to create a serviced component. Serviced Components A serviced component is one that is automatically serviced by the Windows Component Services, allowing managed classes to live within the existing ObjectContext. The key thing here is that the code is still managed, so you get all of the managed benefits, with the addition of transactional integration. A serviced component is a .NET component, but it is hosted inside of a COM+ application, and therefore can access the services offered by COM+. A serviced component has its configuration information held by the COM+ catalog. When you use a serviced component within your application, COM+ will create a context service layer based on the attributes you have assigned to your serviced component. Basically, the context service layer runs within COM+ Services, and communicates with your serviced components, which are still running within .NET. There are several steps to go through to create serviced components:  Derive your class from the System.EnterpriseServices.ServicedComponent class.  Add the TransactionAttribute to your class.  Create a strong name for the assembly.  Add assembly attributes to identify the strong name, and the COM+ application name.  Register the assembly with the COM+ catalog. This can be manually done, or under certain circumstances, done automatically (this is called lazy registration). Creating a Serviced Component Class Creating the class and adding the attributes is simple. Here is an example written in Visual Basic .NET: Option Explicit Option Strict Imports System.EnterpriseServices Imports System.Reflection <assembly:AssemblyKeyFile("BankVB.snk")> <assembly:ApplicationName("DotNetBank")> Namespace Wrox <Transaction(TransactionOption.RequiresNew)> Public Class BankVB Inherits ServicedComponent Public Sub Transfer(FromAC As String, ToAC As String, Amt As Decimal) Dim f As String = "Transferring " & Amt.ToString() & " from " _ & FromAC & " to " & ToAC ContextUtil.SetComplete() End Sub End Class End Namespace Let's take a look at the attributes that have been added to this class. The first two are: <assembly:AssemblyKeyFile("BankVB.snk")> <assembly:ApplicationName("DotNetBank")> The AssemblyKeyFile attribute is used to indicate the file that contains the public and private keys for the strong name for this assembly. Later in this chapter, we will look at strong-named assemblies. These types of assemblies are required if we want to have multiple versions of an assembly executable at the same time on the same system. The ApplicationName attribute defines the COM+ application that this .NET component will execute within. If the application is not found, then COM+ will create an application with the name supplied- in this case DotNetBank. <Transaction(TransactionOption.RequiresNew)> The other attribute that has been included with this component is the Transaction attribute. This attribute specifies the transaction parameter for this component. In this case, we want to make sure that the component executes inside a new transaction. The parameter that we pass is an enum defined as TransactionOption.RequiresNew. The C# version of the serviced component is nearly identical to the Visual Basic .NET version. The only difference is the syntax that is used to denote the attributes within the code. Whereas in the Visual Basic .NET version, we used < > to delineate the attributes, the C# version uses [ ] to indicate the attributes: using System.EnterpriseServices; using System.Reflection; [assembly:AssemblyKeyFile("BankCS.snk")] [assembly:ApplicationName("DotNetBank")] namespace Wrox [Transaction(TransactionOption.Required)] public class BankVB : ServicedComponent { public void Transfer(string FromAC, string ToAC, decimal Amt) { string f = "Transferring " + Amt.ToString() + " from " + FromAC + " to " + ToAC; ContextUtil.SetComplete(); } } } Additional Assembly Attributes As well as the ApplicationName attribute, you can also add COM+ component details, such as:  ApplicationActivation, to determine how the assembly is activated (Library or Server).  ApplicationID, to specify a GUID.  Description, to give the assembly a description. For example, in Visual Basic .NET these would be: <assembly:ApplicationActivation(ActivationOption.Library)> <assembly:ApplicationID("guid")> <assembly:Description(".NET bank assembly")> Accessing COM+ Context To access the COM+ context from the .NET serviced component, you use the System.EnterpriseServices.ContextUtil class. There are no major performance penalties since the cost to transition into COM+ context is very small. The context (including transactions) flows with the call, so transactions automatically flow. Registering the Serviced Component Classes using COM+ services must be registered, which can be done using the Register Services Tool. The syntax is: regsvcs [Options] AssemblyName where Options can be one of: Option Description /fc Find or create a target application. This is a default. /c Create the target application, generating an error if it already exists. /exapp Expect an existing application. /tlb:tlbfile Filename for the exported type library. /appname:name Use the specified name for the application. /parname:name Use the specified name or ID for the target partition. /extlb Use an existing type library. /reconfig Reconfigure the existing target application. This is a default. /noreconfig Do not reconfigure the existing target application. /u Uninstall the target application. /componly Configure only the components, not methods or interfaces. /nologo Suppress logo output. /quiet Suppress logo and success output. Using this utility performs the following actions:  Loads the assembly  Registers the assembly  Generates a type library  Registers the type library  Installs the type library into the COM+ application  Configures the COM+ application For example, to register the bank assemblies: If you then examine the COM+ Component Services, you'll see the .NET components. These can be treated like any other transactional COM+ component. Lazy Registration If a serviced component is used from managed code, and it is not already registered as part of a COM+ application, then the registration and configuration is performed automatically for you. This may seem like an ideal solution, but it does require administrative privileges, so is not suitable for all scenarios. By and large, it is best to manually register components, perhaps as part of the installation. Serviced Component Security Integration with COM+ security is also provided as part of serviced components, allowing access to the SecurityContext object of the COM+ application. For this to succeed the managed code needs to obtain an NT security token and perform impersonation before calling the .NET object. Component Deployment An assembly is used by the .NET architecture to support the sharing and re-use of code. All classes must exist within an assembly in order to be creatable by the CLR. The assembly contains the meta data that the CLR uses to allow the object to function. Without an assembly, the component cannot function. In the past, you could store code in a DLL, and you could use DLLs as loadable modules within an application. The difference though, is in the meta data. A DLL was just a block of code- there was no knowledge of what it did outside of the developer that was familiar with it. The meta data associated with an assembly provides that kind of information. What are Assemblies? There is no concept of an assembly as a file- there is no such thing as a .assembly file that we have to worry about now. The assembly is a collection of files that together make up the assembly. The only requirement is that these files need to all reside in the same directory on the disk. When they are placed into an assembly, the CLR treats all these as a single unit. As you can see from the above figure, the manifest is what is used to describe the contents of the application. The manifest can either be embedded within a single DLL, as seen in the single file assembly, or can be in a separate file, as is the case with the multi-file assembly. When we talk about DLLs in .NET, they are just a bit different from what they were in COM or Win32. While the extension is the same, they are executed by the CLR, instead of being executed as native code. The assembly can be thought of as a logical DLL. In the past, we would distribute components or resources through the deployment of a DLL. Now, we can distribute the pieces of an assembly in the same way. The main difference is that the DLL needed some other information somewhere- usually in the registry- to tell the system that it was there ready to run. With an assembly, it carries that information along with it, in its meta data. An assembly is not an application. An application is built from one or more assemblies. The assemblies that make up an application can be deployed in a number of different ways. Since an assembly contains its own meta data, it is capable of telling the operating system all about itself. It does not rely on entries into the registry to describe itself. This association of meta data with executable code simplifies the distribution of an application. All you need to do to deploy an application is simply to copy all of the assemblies that make up the application to a directory on the disk. This is known as XCOPY deployment, since the only tool required to deploy the files to disk is the XCOPY console command. When the application is first executed, the meta data within the assemblies tells the system all that it needs to know in order to execute the application. As we saw earlier, this may not always be the case. If you are using serviced components, these need to be registered with COM+. You can also use more traditional installation mechanisms to distribute applications built out of assemblies. You can build an .msi file and use the Windows Installer to deploy the files into the correct location. Likewise, you can build a .CAB file and have a browser download the file to the system and then execute the application. In either case, all that the installation mechanism is responsible for is getting the proper files into the proper location on the destination system- no information about the assemblies needs to be added to the registry of the target system. Assemblies and Versioning There are currently two problems with the Win32 architecture that have combined to give us what is known as DLL Hell. In DLL Hell, there is no control entity that is responsible for all of the DLL files installed onto a system. Information about a COM DLL is held in the registry. It can be easily overwritten by another application. For DLLs that aren't COM DLLs, there is no entry whatsoever in the registry. An application install program can also overwrite an existing DLL. This can play havoc with any existing application that was relying on that particular DLL performing a specific function when a method is called. One of the specific problems with Win32 is that there is no system-level enforcement of versioning rules between components. It is left up to 'best practices' coding, which says that once an interface is published it can never be changed, but there is nothing in the operating system that explicitly prevents this. The other problem is that there is no common way for an application to say that it needs version 1.2.1.1234 of a particular component. It is left up to the developer to check the version of a DLL before calling into it. If that check is not done, and the application finds a different version, then the code that it is relying on may no longer be there, or it may not perform the function that it expects, even if the interface is still intact. To attempt to combat this, Windows 2000 added System File Protection. This is an OS feature that can stop any installation program from overwriting any system DLLs. The CLR extends this support by allowing developers to specify the specific version of a component that they want their application to use. It provides all of the support to make sure that the proper version is located and used for the requesting application. In doing this, it also allows for the execution of code from two similar components, only differing in version. This is known as side-by-side execution and we will look at that a bit later in the chapter. Assembly Manifest In order for an assembly to describe itself to the CLR, it must contain a set of meta data. This meta data is contained in the assembly's manifest. The manifest contains the meta data required to specify:  The assembly version  The security information for the assembly  The scope of the assembly  Information to resolve references to the resources and classes of the assembly The manifest for an assembly can either be stored in an EXE or DLL file, or in a standalone file. Remember that the assembly can be made up of one or more files- in which case there isn't a specific file that contains the entire assembly. In a single file assembly, the manifest is part of the DLL or EXE file that is the assembly. The manifest of an assembly lists all of the files and resources that make up the assembly. It also lists all of the classes and types defined in the assembly, and specifies which resources or files within the assembly map to which classes or types. The manifest also identifies any other assemblies on which it is dependent. In creating a multi-file assembly, the Assembly Generation tool ( AL.EXE) is used to create the manifest for the assembly. To create a multi-file assembly, you compile the individual source files without an assembly. Then the AL tool is used to read through the compiled modules and create an assembly for the full set of modules. Meta data The manifest will specifically contain these pieces of meta data:  Assembly Name - This is a textual string name that identifies the assembly. When an assembly is used by one application, the developer can generally enforce a unique name for each assembly, thus preventing name collisions. However, when an assembly is designed to be shared, a more unique naming method must be used. This is called a strong name, and creating one allows the assembly to be stored in the global assembly cache. The global assembly cache is used to store assemblies that can be used by several applications on a machine. To store an assembly into the global assembly cache, there are three steps that have to be followed: First, you must create a strong name for the assembly using the SN.EXE tool. This tool will generate a file that contains the necessary public and private keys to define a strong name. Second, the contents of that file are passed to the Assembly Generation Tool ( AL.EXE) to create an assembly with a [...]... System.Web - the parent namespace for all ASP.NET classes This contains classes like HttpRequest (the ASP.NET Request object) and HttpResponse (the ASP.NET Response object) Again, the code will compile without this, but as with the System namespace, most control classes will use the ASP.NET intrinsic objects so it is good practice to include it System.Web.UI - contains the ASP.NET control classes, many of which... implemented ASP.NET provides a clean and easy-to-use class hierarchy for implementing controls, and there are no esoteric interfaces or threading models that are difficult to understand ASP.NET still uses interfaces, but there really aren't more than a couple you'll use on a regular basis In this chapter we're going to look at ASP.NET control development covering: When, why, and how you can build ASP.NET. .. developers These same advantages apply in the world of ASP.NET controls, but there is one big difference: ASP.NET controls are easy to get started with ASP.NET allows you to build reusable visual controls that can render themselves as HTML or any other mark-up language such as WML Many high level similarities can be drawn between COM controls and ASP.NET controls, as they both enable reuse within UIs... myfirstcontrol.aspx to contain this ASP.NET page This page tells the ASP.NET page compiler that when it sees any element starting with 'Wrox:' it should search the namespace WroxControls for a class whose name matches the element name (that is, MyFirstControl) Furthermore, the assembly attribute defines the physical assembly in which the class is contained At run-time, assuming ASP.NET located the class, it... inside the ASP.NET page code In this page we'd expect the server controls output to be rendered after the body tag In this example, once our control has inserted its HTML into the output stream, the final page sent down to the client browser will look like this: ASP.NET Control Development in C# The actual rendering of which is shown here: To test the ASP.NET page... the lifetime of an ASP.NET page Unlike ASP, where a page essentially had one execution step, 'render', an ASP.NET page has many executions steps or phases As such, control events are fired during different execution stages within a page Control Properties For a server control to be useful it needs to allow a page developer to have influence over how the control renders its UI In ASP.NET pages, the... page: Attribute Value Conversion When ASP.NET matches an attribute to a property, it will perform intelligent conversion of the attribute value If a class property is a string, ASP.NET will just do a simple mapping and initialize the attribute If the property is an integer or long, the attribute value will be converted to a number, then set If a value is an enumeration, ASP.NET will match the string value... implementation of this method calls the Write method of the HtmlTextWriter object, which results in the HTML "ASP.NET Control Development in C#" being written to the page output stream Once you have created a server control and compiled it (as we'll demonstrate shortly), you can use it in an ASP.NET page To do this, you use the @Register page directive to associate a tag prefix with a namespace containing... How controls form the basis of all page rendering in ASP.NET How controls persist state across page invocation How controls interact with postback and can raise events Building controls that, themselves, use other controls to render their UI Writing a Simple Control To demonstrate the basic principles of control development and to show how easy ASP.NET control development is, we'll kick off this chapter... are written so you can better understand how ASP.NET renders pages Creating a C# Control Fire up your text editor or IDE of choice and enter the following C# code: using System; using System.Web; using System.Web.UI; namespace WroxControls { public class MyFirstControl : Control { protected override void Render(HtmlTextWriter writer) { writer.Write("ASP.NET Control Development in C#"); } } . These same advantages apply in the world of ASP. NET controls, but there is one big difference: ASP. NET controls are easy to get started with. ASP. NET allows you to build reusable visual controls. System.Web - the parent namespace for all ASP. NET classes. This contains classes like HttpRequest (the ASP. NET Request object) and HttpResponse (the ASP. NET Response object). Again, the code will. <body> <h1> ;ASP. NET Control Development in C#</h1> </body> </html> The actual rendering of which is shown here: To test the ASP. NET page yourself and

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