Search the Catalog
Developing ASP Components

Developing ASP Components

By Shelley Powers
1st Edition April 1999
1-56592-446-0, Order Number: 4460
510 pages, $29.95

Sample Chapter 1:

Writing ASP Components

When Microsoft first released Active Server Pages (ASP) with the company's web server, Internet Information Server (IIS), the functionality included with this early release amounted to little more than an ability to handle server-side scripting. If you haven't worked with server-side scripting, it is the inclusion of script, such as VBScript or JScript, in web pages so that the script is processed on the server rather than on the client. This early ASP release soon gave way to the ASP we have now, a sophisticated server-side application-building environment that still supports server-side scripting, but also includes integration with other Microsoft server products, such as Microsoft Transaction Server, and also allows ASP pages to access COM objects.

This book is about writing COM objects to work within this specialized ASP environment. Since they are COM-based, you know that whatever functionality you can perform with COM components, you can also perform with ASP components. This means that you can create an instance of an ASP component and use that component instance to do things such as query a database, open a file, or print a file to a printer. However, ASP components are created for a specialized environment, and there are certain things you might consider doing with COM objects that you probably wouldn't consider doing with ASP components. For instance, because an ASP component resides on the server, you aren't going to use any message windows to communicate with the user; all communication is handled through IIS.

In addition, as part of the ASP environment, ASP components have access to built-in objects that contain information not normally available to a "standard" COM object--information such as form field values submitted from an HTML form, the type of browser being used to access the page, or even the language, such as English, preferred by the client.

The information available to an ASP component is also available to ASP scripting blocks, so why use components when you can use scripting? Especially since scripting is fairly simple to use and can be learned relatively quickly?

The first and foremost reason to use ASP components over in-page ASP scripting blocks is reusability. It's difficult to package an ASP script in such a way that it can be used over and over again in many different pages. Additionally, if you or your company is considering packaging some ASP functionality for resale or distribution, the use of ASP scripting becomes insupportable. You probably won't be in business long if people can not only see the source code for your packaged functionality, but can modify it for themselves.

Another reason to use ASP components is that the components themselves can reside virtually anywhere, even on different machines. You can create an ASP application that may update a customer database and that uses one component to update the person's address and another component to update the person's preferences. One or both of these components can reside on the same machine as the web server, but one or both of these components can as easily reside on other machines, with DCOM being used to access the component. While you can distribute web pages containing script on various machines, the maintenance and access issues become much more complicated and usually require hardcoding the physical addresses of the pages within the application. With COM-based functionality, only the operating system COM manager needs to know where the ASP components reside. Moving components is a matter of changing the location of a component once on the client machine; all accesses to the component now occur at its new location.

An additional reason to use ASP components is that they can incorporate the fullest range of functionality on the server, including database access, file access, archiving, messaging, and other functionality difficult or impossible to do with script. You can even transcend object systems and access CORBA-based components with the support of products such as Iona's COM-CORBA Bridge.

NOTE:  

Though ASP can be used with a web server such as the Personal Web Server from Microsoft, this chapter and this book focus on ASP as it is implemented within IIS. If behavior differs based on the web server used, I'll try to add a note to that effect.

Now that I've battered you with some of the reasons to use ASP components, let's take a little look at the history of web development, and see where ASP and ASP components enter the picture.

In the sections ahead, this chapter provides a little more of the history leading up to ASP and an overview of the technologies used when writing ASP components.

A Little History

It wasn't long after the first web browser was released for public use that organizations began to consider how they could use the web for applications beyond downloading single, static pages. Application development proceeded in two different directions: on the client with client-side scripting using JavaScript, and on the server with server-side applications. The earliest server-side web applications used a specification called CGI, or Common Gateway Interface, to create applications that would be executed when they were accessed, and which generated web pages to be returned to the viewer.

The earliest forms of web server development used CGI to perform some functions on the server. CGI is relatively simple in operation. A URL contains a reference to an application rather than a web page. With the application request usually comes data, such as the data from an HTML form being submitted by the web page reader. A separate instance of the CGI application is started to process the request, and the output generated by the application is returned as an HTML page to the viewer. CGI applications can perform simple tasks, such as redirecting the browser to another site or to another web page based on certain factors such as browser type. Or CGI applications can be complex, such as processing an order for an online store. Any programming language can be used for building a CGI application, with the Perl scripting language the popular favorite because of its powerful, if cryptic, capabilities.

To quickly demonstrate CGI, Example 1-1 shows a simple Perl script written for a web site using the Apache web server for Unix. In this example, the host actually has two domains pointing to the same IP address. The script checks to see which domain was used by accessing one of the standard HTTP web server environment variables, HTTP_HOST, and redirecting the browser to the page appropriate for the domain. This Perl script is a small, quick, and efficient little application that performs one specific task.

Example 1-1: A Simple CGI Script That Performs Redirection Based on Domain
#!/usr/local/bin/perl
#
# index.cgi
#
# Application will check for the existence of certain
# key terms to determine which browser the web page reader
# is using.
#
# The CGI environment variable HTTP_HOST is accessed
# and certain substrings are matched against it. If
# a match occurs, the browser is redirected to the
# document that matches the browser.
#
# If no match is found, the browser is directed to a text-
# only web page.
#
# Access environment variable
$browser = $ENV{'HTTP_HOST'};
#
# check for Internet Explorer
if (index($browser,"dynamicearth") >= 0) {
print "Location: http://www.yasd.com/dynamicearth/dynaearth.htm\n\n";
} else {
print "Location: http://www.yasd.com/plus.htm\n\n";
}

Even without knowing Perl, it is relatively easy to determine what is happening with this script. After the host variable is accessed and loaded into a local variable, $browser, it is matched against a specific domain request, in this case a domain containing the word "dynamicearth." If found, redirection is used to point the browser location to one page; otherwise, redirection is used to point the reader to another web page.

Though still the most widely used server-side development technology, CGI is not necessarily the most efficient. Its major problem is that a new instance of the CGI application needs to be loaded for each server request. Several people making several requests at the same time impact the performance of both the CGI application request itself as well as the overall performance of the web server.

Returning to Example 1-1, each person who invokes the index.cgi application at the web site must wait for the CGI application to be loaded and run before receiving a response back. While the performance of this approach is acceptable, especially for simple uses such as this, starting up a new server application for every page, form access, or bit of functionality will soon disrupt overall server performance, and can actually lead to server failure or server page request timeouts.

NOTE:  

Security issues about CGI arose fairly early on, particularly concerning where CGI applications reside and what operations they allow. Read more on security and CGI at http://hoohoo.ncsa.uiuc.edu/cgi/security.html.

The real key to improving the performance of server-side applications is to provide a technique that loads a server-side application into memory only when the application is not already loaded, and which can allow multiple accesses to the same application from different sources. Among the approaches taken to do this were those that included creating web server extensions that exist as part of the web server itself, rather than as separate applications. With this approach, add-ins to the server could be created using an exposed API, and these add-ins would become integrated with the server rather than existing outside the server. Most web server manufacturers, such as Netscape and Microsoft, soon created proprietary methods for extending their servers.

Microsoft's first web server extension was the Internet Server Applications Programming Interface (ISAPI). ISAPI is quick, in that the ISAPI application runs within the same process as the web server, and communication between the server and the application is very fast. Additionally, once the ISAPI extension application is loaded into memory, it stays in memory, and all client accesses to the extension are made to the same ISAPI process. The only time the ISAPI application is unloaded from memory is if IIS is shut down or regular memory management removes it.

Though fast and efficient, ISAPI does have its limitations. First, it is easy to begin building an extension, but difficult to finish. By this I mean that it is relatively easy to use Visual C++ to start an ISAPI component, since Microsoft has provided a built-in ISAPI wizard to create the framework for the ISAPI DLL. However, building on the framework the wizard provides is not so simple. And ISAPI is limited to C++ programming, leaving the Visual Basic and Java folks out in the cold.

Microsoft was aware of the disadvantages of using ISAPI and fairly quickly provided another approach to creating web-server-based applications: Active Server Pages (ASP). ASP provides for simple and easy server-side scripting that allows web developers to use a combination of HTML, along with JavaScript, VBScript, or any other popular scripting language, to create server applications. A key feature of ASP, though, is that in addition to scripting, it also provides for component-based development by allowing the inclusion of COM-based server components.

About the same time Microsoft rolled out ASP, it also rolled out a combination tool/API service to provide for component and transaction management, the Microsoft Transaction Server (MTS). MTS provides for transaction management for COM-based components, ASP or otherwise. In addition, MTS is an effective component management tool, providing not only component registration services, but also server and client migration. With the release of MTS 2.0 and IIS 4.0, Microsoft also provided for an optional integration of the two servers, with IIS providing the web interface and MTS providing component and transaction management.

The use of ASP and MTS is further enriched with the release of OLE DB, which provides for generic data access regardless of data structure, and which also provides for cross-process transaction management with database engines that support MTS. To assist developers wanting to use OLE DB, Microsoft provided the OLE DB Templates for Visual C++ developers and ActiveX Data Objects (ADO) for all developers.

ASP: What It Is and How It Works

Microsoft created ASP in answer to the need for a scalable and efficient web server application technology that is also relatively safe. ASP is fairly simple to use, and all of the applications can actually be created with server-side script using languages such as JavaScript/JScript or VBScript. If some functionality is needed that can't be provided by scripting, ASP components can be used.

How does ASP work? ASP pages are created with a default extension of .asp. When IIS gets a request for a page with an .asp extension, the web server accesses and compiles the script contained within the page and loads the compiled code into memory. The script then performs some processing, which usually generates HTML that is then written out to the ASP page. To perform its processing, the script has access to several built-in ASP objects that contain considerable information about the ASP environment, and which allow the script to communicate back to this same environment. The static and script-generated HTML of the ASP page is then returned to the client using a regular HTTP transaction. To the application user, the page looks no different than another static HTML page except for that .asp extension. This is because all processing of the script has taken place on the server.

NOTE:  

The ASP built-in objects are covered in detail in Chapter 6, Overview of the Intrinsic (Built-in) Objects.

As a quick example, the ASP page shown in Example 1-2 has a small VBScript script block that uses two of the built-in ASP objects accessible to ASP script and components: the Response and Request objects. These are discussed in more detail later in the book, but for now, the Response object provides a way to communicate from the server application to the user, and the Request object is used to communicate from the ASP environment and the user to the server application. In Example 1-2, these objects are used to create a variation on the traditional "Hello World" program.

Example 1-2: VBScript Block with a Variation of the Traditional "Hello World" Program

<HTML>
<HEAD>
<TITLE>Server Variables</TITLE>
<STYLE type="text/css">
BODY { margin: 0.5in }
</STYLE>
<BODY>
<H1> Hello World </H1>
<p>
<strong>
<%
Dim strng
strng = "and hello to you, too, connecting from "
strng = strng & Request.ServerVariables("REMOTE_ADDR")
Response.write strng
%>
</strong>
</BODY>
</HTML>

Once the page containing this script is saved to a file named hello.asp and copied to an existing IIS directory, the work for this ASP application is finished. Accessing the page displays "Hello World" on the browser, with some variations, as shown in Figure 1-1.

Figure 1-1. The output generated by hello.asp

If the ASP page is accessed from a client located at the IP address 127.0.0.1, the HTML that is returned to the browser is similar to that shown in Example 1-3.

Example 1-3: HTML Returned to Browser by the Script in Example 1-2
<HTML>
<HEAD>
<TITLE>Server Variables</TITLE>
<STYLE type="text/css">
BODY { margin: 0.5in }
</STYLE>
<BODY>
<H1> Hello World </H1>
<p>
<strong>
and hello to you, too, connecting from 127.0.0.1
</strong>
</BODY>
</HTML>

NOTE:  

The IP address 127.0.0.1 is also known as localhost or the loopback address and can be used when accessing web pages from a local web server.

An ASP page usually exists as part of an ASP application. An ASP application is really all the pages and associated content of a real or virtual directory, whether the pages have .asp extensions or not. An ASP application can be created by creating a real or virtual web site within IIS, and setting some of the properties for the site, as discussed in more detail in Chapter 2, Setting Up and Maintaining the ASP Development Environment. To change one of the pages within the application is as simple as opening the page in a text editor and making the change, then copying the modified ASP page to the directory where the ASP application resides. When IIS next opens the ASP page, it can determine that the page has changed and recompile the scripts, if the page has any.

NOTE:  

Unfortunately, making a change to an ASP application running from the Personal Web Server is not as uncomplicated, and usually requires a reboot of the server in order to pick up the changes.

As stated earlier, sometimes the functionality for an ASP application can't be created within an ASP scripting block, and a more full-featured programming language or tool is needed. When this situation occurs, the functionality can be incorporated into the ASP page as an ASP component.

ASP and ASP Components

The beginning of this chapter introduced you to ASP components. This section continues this introduction, but in greater detail.

What Are ASP Components?

As stated earlier, ASP components are COM-based components that encapsulate a specific functionality and are invoked either directly from an ASP page or indirectly via some other ASP component. If you have worked with COM before, ASP components don't use any additional technology, but they can use additional objects available only within the context of an ASP application. However, if a component does not access the ASP-specific objects provided through the ASP object model, it can be used within a distributed application, from other components (whether or not they're part of an ASP application), or even within a flat one-tier application, with no involvement with ASP or IIS or even the Internet. From this point of view, this book could actually be about writing COM components, but with a specific focus.

Having said that an ASP component is really no different than any other COM component, I want to add that the focus of writing an ASP component can alter how that component is created. First of all, the component will usually reside on the same server as the "client" of the component, with the client for ASP being the web server. I say "usually" with some reservation, since there is no requirement that ASP components have to reside on the same server as the client application.

In addition, an ASP component is almost always an in-process (ActiveX DLL) component. As you will see in Chapter 3, ASP Components and COM, using an out-of-process component (an ActiveX executable) directly from an ASP page actually requires that the IIS installation be modified. ASP is optimized for in-process access of components.

As in-process COM objects, ASP components are usually created using apartment-, free-, or both-threaded models. ASP components are not and should not be created using the single-threaded model, since the component locks down all access to a single thread, which causes access problems in a multi-user environment such as the web and a multi-user application such as a web server. In addition, when using multithreaded models, the ASP components must be thread-safe. What's a thread-safe ASP component? One that does not contain global data, does not yield control internal to the processing of the component, and is safely reentrant. Chapter 4, ASP Components and Threads, goes into more depth on threads and apartments.

Now that you have a basic idea of what ASP components are, the next section discusses why you would use ASP components instead of creating the ASP application using scripting exclusively.

Why Use ASP Components?

In the beginning of the chapter, I started listing some reasons to use ASP components instead of scripting. In this section I want to discuss this in a little more detail.

From a perspective of usage, an ASP component can be used in place of scripting where scripting is just not workable or efficient. For example, your ASP application may need to make direct calls to the Windows internals through the Win32 API, or to manage file input and output. These operations cannot be done from within a scripting language such as JScript or VBScript. The IIS scripting engine can be extended to other scripting languages, such as Tcl or Perl, which do support direct file system access or calls to the Win32 API. However, the use of these scripting languages comes at a cost: the code is a little more difficult to read, a little more difficult to maintain, and a whole lot more difficult to secure against editing from external sources. If the code needs to remain unaltered, perhaps to enforce standards compliance or universal data access, the code should be contained within binary components.

Along with implementing functionality that is either unsupported or not easily supported by scripting languages, ASP components are also developed to be reusable and to wrap routines that are commonly called in ASP applications. It is true that ASP scripts can also be reusable; however, this requires copying and pasting the script and duplicating it in all the documents that need its functionality. This means that if the code needs to change, the change then needs to be propagated to all the pages that use the code. In contrast, reusable code is more easily and efficiently managed through components. All ASP applications can access a single physical component. And when that component needs to be modified or revised, the change needs to be made in just a single place. So for code that needs to be reusable, an ASP component is a better choice than ASP scripting.

ASP components can be used to modularize an application, splitting off discrete, manageable bits of functionality that can then be coded by several people in parallel or even purchased from some other party. An additional advantage to modularization of code in components is that the components can themselves be distributed on different machines, and component access can be handled remotely through DCOM or some other equivalent technology. This approach ensures that the application is more scalable and will be able to handle increasingly larger numbers of accesses. If the ASP components are also configured and coded as MTS components, transaction management for all of the components can be handled directly by the Distributed Transaction Controller (DTC) regardless of where the component resides. Though transactions can be used with scripting, and ASP pages can be located on other machines, the management of doing both with pages containing straight scripting blocks instead of components can become more complicated.

If an organization is considering building an n-tier application rather than fitting within the traditional client-server paradigm, ASP components are an excellent tool to use to implement one or more of the application layers. A classic approach is to implement the business layer of an ASP application as one or more ASP components, and to handle the presentation layer in the web page using HTML and client-side scripting, including the newer Dynamic HTML (DHTML). The data access layer would be contained within the database used in the application.

Finally, ASP components are a handy way of ensuring uniformity of an application. For example, if database queries are formatted for output into HTML tables with a certain look, the data presentation functionality can be maintained within ASP components in a layer between the web pages and the business logic, and used for all database queries.

Once sold on using ASP components, as I hope you are, the next choice is the tool or language to use.

Choosing the Language: Java, C++, or Visual Basic

In actuality, there is no "right" tool or language to use for writing ASP components. Any tool capable of creating in-process COM objects can be used to create ASP components. This includes Visual C++, Visual J++, and Visual Basic from Microsoft. This also includes Delphi from Inprise (formerly Borland), PowerBuilder from Sybase, and a host of other tools. However, if a company has chosen ASP as an application development environment, it is more likely that the company is using a Microsoft tool for developing the components, which is why this book covers writing ASP components using the Microsoft tools.

NOTE:  

Though this book covers Microsoft tools, the technologies and the samples, though not necessarily the framework or the step-by-step instructions, can be used with any C++ tool that supports COM or, like C++Builder from Inprise, that supports the use of ATL. The same applies to Java; if a tool supports the new Java WFC classes and Java-wrapped COM access, and can run with Microsoft's Java VM, it can be used to develop ASP components that work with IIS.

As for which language to write the component in, there is no one choice that stands out clearly over the others. Writing ASP components using Visual Basic exposes less of the underlying functionality than writing the same component using Visual J++ or Visual C++. Because of this, Visual Basic is the easiest tool to use, particularly for a shop that has primarily used tools such as PowerBuilder or Visual Basic for most application development. If a shop is porting a traditional Visual Basic client-server application to an n-tier system, the continued use of Visual Basic also makes sense. Chapter 9, Creating VB Data Access Components, and Chapter 10, Creating N-Tier ASP Components Using Visual Basic, provide coverage of writing ASP components for this type of environment.

However, for a Java shop, it makes no sense to switch to Visual Basic when using Visual J++ or a comparable Java-based development tool is just as effective. Microsoft has provided a set of Java wrappers for the ASP built-in objects, and Visual J++ handles all COM interfaces automatically. The main concern of a Java developer writing ASP components is to ensure that all data types used for parameters are CORBA-compliant, which also makes them relatively safe for COM. Chapter 15, Creating a Simple Java Component, covers the Java/COM concerns, and Chapter 16, The Java Interfaces, discusses how to access the built-in ASP objects. In particular, Chapter 18, Java ASP Components and J/Direct, Native Code, and Marshaling, covers native API access, which could be important for some of the components you might develop.

NOTE:  

At the time of this writing, Microsoft is being sued for its extensions to the Java language. Wherever possible, notes are inserted into the Java chapters that detail what may or may not change based on the outcome of this lawsuit.

Visual C++ exposes more of an ASP component's underlying COM architecture and can be used to create the most efficient and speedy components. However, that same exposure to COM also makes using Visual C++ a more difficult choice. If the shop creating the components has no C++ or Visual C++ experience, this approach becomes prohibitive. However, if a shop has used Visual C++, then Microsoft has provided the ActiveX Template Library (ATL) to assist in implementing ASP components; it handles almost all of the details associated with the implementation of a COM component. Using ATL and accessing the ASP built-in objects are covered in Chapter 11, Creating a Simple C++ ASP Component, and Chapter 12, The C++ ASP Built-in Interfaces. In addition, Chapter 14, Persistence with ASP Components Using ATL and MFC, also provides coverage of file I/O in addition to serializing information for persistence beyond the life span of an ASP application.

As for concerns about interoperability, considering that ASP components are COM components, they are by their very nature interoperable within a COM environment. Even within an organization that uses CORBA rather than COM, there are COM-to-CORBA bridges to handle communication between the two component management/communication approaches.

The underlying language used to create the component does not matter because ASP components are based on a binary interface, not a language-specific interface. This does, however, limit their portability to only those systems that have COM support.

NOTE:  

Needing COM and working with ASP does not necessarily mean that an ASP component will only reside on a Windows NT or 9X platform. Chili!Soft has implemented a product called Chili!ASP to process ASP pages from servers such as Netscape, including Netscape running on a Unix box. See the Chili!Soft web site at http://www.chilisoft.com/ for more information. In addition, Software AG, with a web site at http://www.softwareag.co.uk/, has ported DCOM to Unix, and there is an interesting article on building COM components on Unix at http://msdn.microsoft.com/developer/news/feature/vcjune98/unixcom.htm.

Integrating MTS with ASP Components

MTS is a component/transaction management system that can be used to register components, package them for transportation and installation, expose the objects for remote client access, and work with the DTC to actually manage transactions. In addition, MTS also provides support for stateless components and resource pooling, concepts discussed in this section, as well as in Chapter 5, Components, Transactions, and the Microsoft Transaction Server.

Transaction Management

Late in 1997, Microsoft released version 4.0 of IIS and version 2.0 of MTS. The company also provided for transaction management within and between ASP components through the use of an MTS built-in object called ObjectContext. ObjectContext can be used to commit or roll back transactions, and the built-in ASP objects can be accessed directly through ObjectContext in order to include them within the transaction processing.

If an ASP component performs a task that begins and finishes within a single function call, transaction management is not that much of an issue. However, ASP components can call other components and perform other actions such as database activity, each of which requires some form of overall transaction support.

One of the problems with a distributed application (an ASP application can be distributed) is transaction management across several different application components, and potentially across several different machines. For instance, one component can update an address in a database, and another component can update an associated name. If the address update fails, the associated name update should also fail in order to maintain consistency of the data. If both of the updates occur within the same component, this isn't a problem, since both database transactions can be rolled back. Rolling back a change means that the impacted database data exists in the same state as it did before the change was attempted.

If the updates occur with two different components, transaction management becomes more complex. One possibility is to use one database connection for both components, and one of the components--the one making the name update--calls the other component that performs the address updating. The component performing the address update returns a value signifying success or failure of its operation. If the update failed, the first component would not make its update. Though workable, the approach is cumbersome, and neither component is able to work independently of the other.

Another approach is to handle transaction management within an ASP page or by a third component that creates both updating components, tests the return state of both components, and commits or rolls back all of the changes based on the results returned by either component. This is a better solution, since now both components can make their updates without having to worry about what is happening with any other component. However, in a larger application that makes multiple changes of this type, having the application itself maintain consistency between the data updates of all the components can become overwhelming at some point.

The best solution of all is to have some other process manage the transaction state of the components and test to see whether each component has succeeded in its operation or whether one of the components has failed. If any one of the components fail, then the changes made by all of the components are rolled back. This is where MTS and the Distributed Transaction Controller (DTC) come in.

The DTC is an NT system service, first introduced with Microsoft SQL Server 6.5, that provides for two-phase transaction management of all data updates. A two-phase commit transaction management ensures that all participants in a transaction complete successfully, or none of the participant updates are committed. You might say that this first phase of the commit operation consists of a pass made of all participants in a transaction to ask if they are ready to commit their changes. The second pass then checks to make sure all of the components have made updates without errors.

The DTC was also incorporated into MTS to extend transaction management to all components regardless of whether they perform data updates to SQL Server or some other data store. MTS can provide transaction management for components even if the components are distributed over various machines and environments.

ASP applications can participate in MTS transactions, and transaction management can occur within an ASP page, an ASP component, or both. A transaction can be created within an ASP page that is then used for all of the components created directly from the page, or created from within another component accessed in that page. Failure in any one component means all of the updates made by all of the components within the transaction are rolled back. Components themselves do not have to create transactions directly, but can be registered with MTS in such a way as to participate in an existing transaction or have MTS automatically create a new transaction for the component when the component is created.

To control transactions from within a component, all the component needs to do is complete its code. To participate in resource management, if the component uses the MTS transaction methods setComplete and setAbort, the component is basically providing information to MTS that it has finished its processing and can be unloaded from memory. The following code is an example of using setAbort from within a Java component:

IObjectContext iObjContext;
 
// get instance of ObjectContext associated with ASP component
iObjContext = (IObjectContext)MTx.GetObjectContext();
...
iObjContext.SetAbort();

By using the ObjectContext object's SetAbort method, MTS knows that the component has finished its processing, but that the processing was not successful. In a two-phase commit paradigm, the object passes the first phase successfully; it is finished with its processing. The second pass of the process would operate on the information that this component failed, which means the transaction failed and none of the updates made by any component in the transaction are committed.

Using the SetAbort method also lets MTS know that it can unload the component from memory even if the client of the component still maintains a pointer to the component. When the client next accesses the component, MTS loads a new version of it and passes all component references to the new component. This concept of just-in-time activation is a product of another aspect of MTS, which is its resource control and pooling service, discussed in the next section.

Resource Management

To understand what MTS can provide for resource management with an ASP application, you'll need an introduction to the concepts of resource pooling, resource dispensers, and resource managers. These topics are covered in Chapter 5, but an overview of the technologies would be useful now.

Resource pooling recognizes that some resources--such as database connections, threads, or other finite resources--are expensive. By preallocating a pool of resources, access to the resource happens more quickly. Since quick allocation of the resource is assured, the developer will most likely write code that allocates the resource, uses it, and releases it as soon as possible. When the developer uses this type of coding practice, the pool of available resources can be kept small. By keeping the resource pool as small as possible, the whole system performs better, and the developer receives positive feedback--a nicely performing application or component--encouraging the developer to continue using the sound coding practices that actually assist in the well-behaved application or component. This is just the kind of cycle that should be encouraged with development.

By utilizing resource pooling, expensive and time-consuming resources such as database connections can be created when the application is started and can be used for all resource access, rather than having to create a new reference every time the application wants to create a new connection. Based on resource pooling, the connection happens more quickly, and the system is more scalable, since limited resources are managed finitely and controls are maintained on the number of resources allocated.

Database connections are the most widely known resource that participates in resource pooling, but any resource can be managed in this manner by creating the appropriate resource dispenser. MTS provides for resource pooling of ASP or other components by providing an object called ObjectControl that actually allows the component to be used within a resource-pooling context. Additionally, for specific resources, developers can actually create dispensers that manage allocating the connections for any resource they think would benefit from this process.

In addition, to support resource pooling, MTS also provides for just-in-time activation, which means that when a client makes a connection to a component managed by MTS, it is really getting a connection provided by MTS and not directly by the component. If the component signals that it is finished with its process, using SetComplete or SetAbort on the component's associated ObjectContext object, MTS knows that it can mark the component for release, even while the client still maintains the connection to the component. When the client next accesses a method on the component, MTS loads a new instance of the component and the client is never aware that it is no longer using the original "component reference."

Accessing Data with ASP Components

There are few applications, Internet-based or otherwise, that do not perform data access in one form or another. ASP applications are no exception. There are actually several methodologies that an ASP application and an ASP component can use to manage or query data.

RDO and DAO: Earlier Data Access Techniques

First of all, an ASP component may access data through a set of APIs provided by the data source engine that allows direct access to the data. Though efficient, the problem with this approach is that the data access is locked into the particular database engine. An additional problem is that there is no guarantee that the API may not change over time, forcing changes to the component using it. An example of using a direct call-level interface is DB-Library for SQL Server.

If the data source has an ODBC driver, the ODBC call-level interface could be used instead. The advantage to using ODBC is that the same techniques to query and manage data for one data source can also be used for another data source, as long as both data sources provide a compliant and compatible ODBC driver. However, this technique does require a fairly in-depth understanding of ODBC.

Microsoft provided the Data Access Objects (DAO) for access to the Jet database engine that ships with Visual Basic and Access. The advantages of DAO are that it is optimized for ISAM or Jet database access, and it can support single queries against multiple data sources. The disadvantages to using DAO are that it is not an optimum approach to access data from relational data sources, and it requires more memory than other approaches such as the Remote Data Objects (RDO) discussed next. Also, before the release of ODBCDirect, DAO could not be used with ODBC data sources. ODBCDirect now provides RDO functionality from DAO objects, though the other limitations remain.

RDO are really wrapper objects for the ODBC API, but lessen the complexity of using ODBC. RDO provides for powerful functionality, including the use of local cursors and batch operations. RDO is fast and efficient, but its performance can actually degrade or it can even fail when used with ISAM data sources.

Data access techniques tend to support certain particular types of data access. Some, like DAO, are geared for ISAM data access, and others, like RDO, are geared more towards relational database access. In addition, none of the approaches are designed to access data from text files, email, or any other of the many data sources that we use on a day-to-day basis. To address the gaps in data access, Microsoft proposed the concept of Universal Data Access, discussed next.

Universal Data Access

Universal Data Access is nothing more than a single data access technology that can be used with different types of data, regardless of the format or structure of data source. This means that the same objects can be used to access an ISAM data source, a relational database, a text file, and even data from email.

To support the concept of Universal Data Access, Microsoft used COM as an implementation paradigm and created OLE DB. OLE DB is a set of interfaces based on COM that provide for data access through data providers that produce and control data, and data consumers that use the data. In this context, SQL Server is considered a data provider, and an ASP component that uses OLE DB directly is a data consumer. Chapter 13, Integrating Data Access in C++ ASP Components with OLE DB, covers using the new OLE DB templates to access OLE DB from a Visual C++ component. As a demonstration of how uncomplicated OLE DB can be with the use of these templates, Example 1-4 displays a component method implemented in Visual C++ that uses the OLE DB templates to create a table query and process the returned result set.

Example 1-4: Creating a Query and Processing the Results
STDMETHODIMP CobjFive::test()
{
// variables
CDataSource connection;
CSession session;
CTable<CAccessor<CAuthorsAccessor> > authors;
 
_variant_t vbreak;
vbreak = "<p>";
 
 
// Define the DB Property Set
CDBPropSet dbinit(DBPROPSET_DBINIT);
 
// Set the connection properties
dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("sa"));
dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));
dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("MARVIN"));
dbinit.AddProperty(DBPROP_INIT_LCID, (long)1033);
dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
 
// initialize the database connection
connection.Open(_T("SQLOLEDB.1"), &dbinit);
 
// open the session
session.Open(connection);
 
// open the rowset
authors.Open(session, "dbo.authors");
 
// move through the records and output last name
authors.MoveFirst();
 
while (authors.MoveNext() == S_OK) {
CComVariant vt(authors.m_aulname);
m_piResponse->Write(vt);
m_piResponse->Write(vbreak);
}
return S_OK;
}

OLE DB is very fast and efficient, but not necessarily simple to understand or use outside of the OLE DB templates for Visual C++. To assist developers in using OLE DB, Microsoft also provided the ActiveX Data Objects (ADO), a set of objects implemented on top of OLE DB that can be used with any programming language or tool that has COM access.

ADO consists of a very small set of objects (only seven) that can be accessed either hierarchically or directly. One of the disadvantages of both DAO and RDO is that their objects form an enforced hierarchy, and any one object can only be accessed from its parent objects within the hierarchy. With ADO, an object like a result set can be accessed and used directly without having to access it from either a command or a database connection, unless this hierarchical access is what you want.

The seven ADO objects are:

Connection object
Creates data source connections and maintains connection information
Command object
Holds data source commands, including those that execute without a returning result set
Recordset object
Holds query information and maintains row data and information about the rows
Field object
Holds information about a specific column within a result set
Parameter object
Used to map program parameter information to the parameter passed with a database command
Property object
Built-in information about each of the ADO objects
Error object
Holds information about any errors that result from some data action

The one major limitation to using ADO is that the objects can only be used for data manipulation such as queries and updates or stored procedure calls. ADO cannot be used for defining data structures, such as creating or dropping tables.

In Chapter 9, ADO is used to demonstrate basic data access techniques with ASP components created using Visual Basic. In addition, using ADO with Java is demonstrated in Chapter 17, Integrating Java ASP Components with ADO and MTS. However, both of these chapters assume a basic familiarity with data access techniques in general, as well as with SQL.

Further Reading

For additional reading about the topics covered in this chapter, check out the following:


oreilly.com Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts
International | About O'Reilly | Affiliated Companies | Privacy Policy

© 2001, O'Reilly & Associates, Inc.