This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND



Advanced Basics
Ted Pattison

WebClasses and MTS

W
hen it comes down to it, Web-based applications are really no different from other UI-intensive programs. Your clients navigate between pages and run queries and transactions. A Web-based app requires code to interpret each request that a client makes, and it's your job to provide the logic for executing the code associated with a specific request.

       What makes this task tedious and error-prone is that many Web developers write the logic to interpret and to process the client's request with ASP scripts. They use VBScript or JScript® with Visual InterDev™—or a real man's code editor, such as Visual Notepad. Visual Basic® 6.0 allows you to replace this primitive style of development by programming and compiling WebClass components inside the Visual Basic 6.0 environment.

       A WebClass is a customizable Visual Basic component in which you write code to interact with the browser-based clients visiting your Web site. On one side of the Internet, a client is clicking on links and buttons inside a browser . On the other side, an instance of your WebClass is running inside the Microsoft® Internet Information Server (IIS) runtime and is responding to her request by executing code that you've written to access your company's database in a DBMS such as SQL Server™ or Oracle.

       If you've read any of my previous columns or articles, you probably know I am a big advocate of replacing ASP scripts with Visual Basic code whether or not you're using WebClasses. Writing logic in Visual Basic for Applications with the Visual Basic IDE has many advantages over using a language like VBScript or JScript. You have compile-time type checking, better IntelliSense®, and direct access to the Win32® API. What's more, your code runs much faster. It's compiled and you experience direct vtable binding when you program against other COM components such as ADO and the built-in ASP objects. An ASP script can only talk with other COM components through IDispatch and late binding.

       I strongly encourage you to be on the lookout for ways to write and maintain more of the logic for your Web site in Visual Basic and less in ASP scripts. This month I'll discuss when you should use WebClasses instead of Visual Basic-generated COM components. Both WebClasses and these Visual Basic-generated components have their advantages, and a large site can benefit from having a mixture of both. If you want to learn the nuts and bolts of WebClass development, you should read "Adding a Touch of WebClass to your Server," by Jason Masterman, page 28 in this issue of MIND. I'm going to discuss the why and where of using WebClasses so you can make informed decisions during the design phase of a large Web application.

The WebClass Framework

       Let's start from the bottom. ASP is a framework built on top of IIS. It's meant to give Web developers the ability to write server-side logic for IIS applications without having to write isapi extension DLLs. ASP provides a set of built-in objects including Request, Response, Session, Application, and Server. You program against these objects and they make calls into isapi on your behalf. These built-in ASP objects are accessible to scripting clients. They are also accessible to Visual Basic-based components that have been programmed against the ASP type library.

      With the release of IIS 4.0 and the Windows NT® Option Pack, the IIS runtime has melded with the Microsoft Transaction Services (MTS) runtime. This makes it possible to run MTS objects inside the IIS Web server process, as shown in Figure 1. When you create IIS/MTS components with Visual Basic, you can easily get at the built-in ASP objects through the ObjectContext interface. You can also use the MTS programming model to run distributed transactions with the DTC just like you can in an MTS server package.

Figure 1: Running MTS Objects in IIS
Figure 1: Running MTS Objects in IIS

      WebClasses represent another framework for Visual Basic programmers that's built on top of the ASP framework. The Visual Basic team designed the WebClass framework to give Web developers the ability to write code for generating Web pages and interpreting client requests. The Visual Basic team's primary goal was to replace ASP scripts with code written inside the Visual Basic IDE. When you finish developing a WebClass application, you compile it into a DLL. Once the DLL is compiled, it can be installed and configured on the production Web server.
When the Visual Basic team designed the WebClass framework, they decided to maintain compatibility with both IIS 3.0 and IIS 4.0. This means that your WebClass DLLs can be used on any Web server that's running either version of IIS. One consequence of maintaining compatibility with IIS 3.0 is that WebClasses do not take advantage of any new features added to IIS 4.0—like the integration between IIS and MTS. IIS 3.0 doesn't know anything about the MTS runtime, and neither do WebClasses. Once you understand this limitation, it's easier to decide where you should use WebClasses and where you should avoid them. As you will see, WebClasses are great for creating presentation layer components that interact with the client, but they are often inappropriate for maintaining business logic and data access code.

The WebClass Manager

      Each WebClass application is controlled by a single instance of the WebClassManager component. When you create a WebClass project, the Visual Basic IDE creates a special ASP page that serves as an entry point into your application. This ASP page has conditional logic to create the one and only WebClassManager instance, if it hasn't already been created. Afterward, this ASP page directs all incoming requests to the WebClass instance manager:



 WC_Manager.ProcessNoStateWebClass "MyApp.MyWebClass",
                                    Server, _
                                    Application, _
                                    Session, _
                                    Request, _
                                    Response
      The WebClass manager is an object supplied by the framework. You never interact with this object directly. It works entirely behind the scenes, creating instances of your WebClasses and calling into them to execute your code. Figure 2 shows the routing of each request from the browser into your WebClass code.
Figure 2: Routing Requests to Your WebClass
Figure 2: Routing Requests to Your WebClass

      The ASP script passes a reference to each of the five built-in ASP objects—Request, Response, Session, Application, and Server—to the WebClass manager. The WebClass manager simply forwards these references to your WebClass instance, which makes it possible for a WebClass to expose these five objects to you by name. You can always program against them directly when writing code inside a WebClass module. This makes it easier than using standard Visual Basic components where you must retrieve a reference to built-in ASP objects using the ObjectContext interface.

      In the code shown previously, the ASP page calls into the WebClass manager through a method called ProcessNoStateWebClass. The WebClass manager will create and release an instance of your WebClass for each request. Each WebClass has a StateManagement property that can be adjusted through a property sheet in the Visual Basic IDE. If you change this setting from NoState to RetainState, Visual Basic changes the ASP script to call the WebClass manager through a ProcessRetainInstanceWebClass method. This directs the WebClass manager to hold onto a single instance of your WebClass for each client across requests. The WebClass manager retains a WebClass instance by sticking it in an ASP Session variable.

      If you choose the RetainState option, you can add module-level variables in a WebClass to hold onto state across requests. However, the cost of this convenience is quite high. Like all other Visual Basic components, WebClasses are apartment threaded. Assigning an apartment-threaded object to an ASP Session variable will pin the client to a single thread from the IIS thread pool. The February 1999 Advanced Basics column discussed the IIS/ASP threading architecture indepth. In that column, I argued that apartment-threaded objects should always be destroyed at the conclusion of each request.

      I recommend that you leave the StateManagement property set to NoState. This will provide a much higher level of scalability. It will also force you to design other means of retaining state across requests. This month's WebClass article by Jason Masterman discusses a few strategies for holding state across requests that will scale much better than retaining WebClass instances.

Building a Browser-based UI

      One of the most valuable features that WebClasses provide is the ability to generate HTML page content dynamically. As long as you know how to work with HTML, you can write the Visual Basic code required to parse together Web pages at runtime. Once you've built a page dynamically, WebClasses make it pretty simple to send the page back to the client's browser.

      The Visual Basic IDE also lets you integrate HTML templates into a WebClass application. This means you don't have to start from scratch when you begin to construct a customized Web page. The WebClass framework provides a scheme for running a search and replace operation on special tags inside an HTML template. You can create the layout of your pages with a WYSIWYG editor like FrontPage®, and then insert customized data into them just before sending your pages back to the client. As you can see, HTML templates give you a nice way to keep your layout details separate from your code.

      Creating a pretty user interface dynamically is only half of the WebClass story. The WebClass framework also provides the means for putting code behind various UI elements on a Web page such as links and command buttons. A WebClass serves as a command-dispatching device that directs each incoming client request to the appropriate processing code. Once you learn how to dispatch client requests, it's easy to give your clients the ability to navigate between pages and to execute queries and transactions.

      WebClasses are based on an event-driven paradigm. Your clients click on links and command buttons and you respond to these actions by supplying WebItems and coding up events. The key concept is that a WebClass allows you to write and maintain all the request-handling code for an entire Web site in a single class module. Compare that to writing and maintaining the same logic in ASP scripts spread across tens or hundreds of ASP pages. WebClasses give you a level of control that you've never had before in ASP.

Business Logic and Data Access Code

      WebClasses are great for building a browser-based UI and for dealing with user interaction. However, there's other code in your applications that you don't want to put in a WebClass. Let's look at an analogy between WebClasses and an older style of development with which you're probably familiar. In the past, many developers created desktop applications based on Visual Basic forms. Working with these forms is similar to working with WebClasses in the sense that you're creating a UI and responding to user interaction through form-level event handlers.
Now answer this question: should you write business logic and data access code inside an event handler in a Visual Basic form module? Absolutely not. In fact, Visual Basic newbies who do this are often ridiculed by experienced developers. If you start adding business logic and data access code into your WebClasses, you will open yourself up to the same type of humiliation.

      Sophisticated three-tier designs partition the business logic and the data access code from the presentation layer code. This discipline is what separates large Web applications designed for corporations from a simple Web site that was created on a Saturday night by the owner of your local pet store. You should be wary of a large-scale design in which a WebClass contains extensive business logic or directly connects to a DBMS.
I strongly encourage you to write business logic and data access code in ActiveX® DLLs instead of WebClasses. Not only will this approach let you partition your middle tier code from the presentation tier code, it will also let you take advantage of the MTS runtime to run distributed transactions. Once your WebClass project references these other ActiveX DLLs, you can add code to your WebClasses to run transactions and retrieve the data you will parse into HTML.

      One important decision you must make during the design phase is how to move data between your data access code and your WebClass projects. If you want a strict separation of user interface code from data access code, you should avoid any ADO programming inside WebClasses. If you take this approach, you must move the data into your WebClasses using the Visual Basic for Applications variant datatype. You can use the GetRows method of an ADO Recordset object to convert a set of rows and columns into a variant array. You can pass the array from an ActiveX DLL to a WebClass using a method parameter or a return value. Once you've passed the array to a WebClass, you can enumerate its contents using standard Visual Basic techniques to parse the data into an HTML page.

      If you relax the requirements of separating user interface code from data access code, you can include a reference to the ADO Recordset type library in your WebClass project. This type library allows you to program with ADO recordsets, but it prevents you from programming with ADO connections or commands. If you take this approach, your WebClasses can utilize ADO recordsets passed from ActiveX DLLs, but your WebClasses still cannot connect to a DBMS themselves.

      This approach allows you to build HTML pages in your WebClasses using ADO recordsets. At the same time, your WebClass DLLs avoid dependencies on the location and format of the DBMS. Some ingenious programmers have even found a way to embed HTML tags into the string returned by the GetString method of an ADO Recordset object. This makes it easy to generate HTML tables dynamically from the data inside your database.

WebClasses and MTS

      As I mentioned earlier, the WebClass framework avoids any integration with MTS to allow for compatibility with IIS 3.0. This means that WebClasses cannot be transactional. That's really not a problem because you'd never want to control a transaction from presentation tier code. This also means that you shouldn't be programming against the MTS type library in a WebClass project. You should be using the New operator to create COM objects instead of using the CreateInstance method of the ObjectContext interface as you would in an MTS component.
WebClass projects should not be programmed against the MTS type library, but the ActiveX DLLs that hold your business logic and data access code should be. This is especially true if you want your components to run MTS transactions. This implies that you should register WebClass DLLs with regsvr32.exe and your ActiveX DLLs with MTS. You can register MTS components from an ActiveX DLL by using the MTS Explorer or by using a script.

      When you install components from an ActiveX DLL into MTS, you must choose between a server package and a library package. If you install your components into a server package, they will run in a separate process that's isolated from the Web server and from your WebClass code. However, if you install your components into a library package, all your objects will run inside the IIS Web server process. This will provide the best possible performance because there are no cross-process calls.

      When you begin writing a Web application that mixes WebClasses and MTS components, debugging becomes a little more challenging. Visual Basic makes it pretty simple to debug a WebClass application. Visual Basic also makes it possible to debug MTS components as long as you are running Windows NT 4.0 with Service Pack 4. However, a single session of the Visual Basic IDE cannot simulate the WebClass runtime environment and the MTS runtime environment at the same time. You need to run two sessions of the Visual Basic IDE.

      To do so, open the ActiveX DLL projects that contain your business logic and data access code in one session of the Visual Basic IDE. Make sure to set the MTSTransactionMode property of your components to any value other than Not An MTS Component. When you run your project from the Start menu, Visual Basic will temporarily register your components in an MTS library package. When a client attempts to create objects from these components, they will be loaded into the Visual Basic debugging environment along with the MTS runtime (mtxex.dll).
At this point you can debug your WebClasses in the other session of the Visual Basic IDE. As long as you have included a reference to your other ActiveX DLLs in your WebClass project, you can debug your WebClasses as usual and single-step between the two sessions of the Visual Basic IDE. Remember that while you must do your debugging with two processes, you can run everything in the IIS Web server process when you deploy it.

Conclusion

      WebClasses make it easy to create the front end for a Web application. Once you understand how the framework has been put together and get up to speed on how to use the supporting features in the Visual Basic IDE, you'll be surprised at how quickly you can create a fancy Web application. What's more, your application can serve up either pure HTML or it can use Microsoft Internet Explorer-specific features such as client-side ActiveX controls. It's your choice.

      During the design phase, you should chart out which components you'll create using WebClasses and which ones you'll create using ActiveX DLLs. Carefully think through the interfaces you will expose from your business objects in ActiveX DLLs. The code you write in your WebClasses will be using these interfaces to get at all the middle tier services you have worked so hard to create.


From the April 1999 issue of Microsoft Internet Developer.