Splitting Code Between ASP Pages and Components

[Previous] [Next]

Now that we've covered the basics of developing and deploying Visual Basic components for an IIS application, I'd like to discuss some of the important factors that affect the way you design an application for IIS. Deciding how to partition application code into ASP pages and Visual Basic components is critical.

If you're designing the high-level architecture for a new Web application, you can typically break down your application code into three logical tiers. You have data access code, business logic, and user interface code. In the initial design phase, it's important to decide how and where to package the code for each of these tiers.

For most of us, the decision where to put the data access code and the business logic should be easy. They should be written into components and distributed in COM-based DLLs. The components should then be configured in COM+ applications or run as nonconfigured components. Once the components holding your business logic and data access code are in place, the developers responsible for the user interface can create desktop and Web-based applications. The client applications that define the user interface use your business objects as an entry point into your company's IT infrastructure.

Creating a great Web application requires expertise in many different technologies. Many of these technologies center around the presentation tier. In this book, I won't cover how to build a sophisticated and interactive user interface (an undertaking that requires extensive knowledge of DHTML and JavaScript). Instead, I'll concentrate on the code that runs in IIS that sends the user interface portion back to the browser.

As you know, ASP pages are critical because they allow you to run server-side scripts that, in turn, allow you to activate and run COM objects in response to client requests. ASP pages are also used extensively to package the content, the layout details, and the user interface code behind Web pages. But exactly how much should you put into ASP pages? That's an easy question to answer: It depends.

Some Web developers like to define every aspect of the user interface using ASP pages. Others go to great pains to minimize what they need to put in their ASP pages. Many developers favor using a mixture of ASP pages and components for generating HTML dynamically. Whichever approach you take, some part of your application must be responsible for defining the user interface.

Any nontrivial Web application must do the following things: it must accept input that the user has entered in HTML forms, it must interpret user requests and run the appropriate commands, and it must generate HTML that contains page content and layout details and send it back to the browser.

Let's examine a few approaches to building the code for the presentation tier. Each approach offers its own set of trade-offs in terms of productivity, reusability, maintainability, extensibility, and performance. Whatever approach you choose, you have to write code against the built-in ASP objects (such as Request and Response) and you have to create and run business objects. You also have to generate HTML for page content and layout and send it back to the browser.

So how do you decide whether to put presentation tier code in ASP pages, compiled code, or a mixture of the two? You should ask yourself the following questions. How fast do you want to get your site up and running? Which is more important, development productivity or application performance? How important is code reuse? Are you willing to invest more time at the beginning of the project to improve the maintainability and extensibility of your site? Do you want to be able to change various aspects of your site without recompiling any code? Your answers to these questions will lead you to a decision.

Creating the User Interface with ASP Pages

Embedding your presentation tier code in ASP pages using a tool such as Microsoft Visual InterDev has its advantages and disadvantages. On the positive side, you can quickly create and modify the layout of Web pages. You can write server-side scripts that use ASP objects such as Request, Response, Session, and Application. You can create and run custom business objects. And finally, you can add the code and static HTML to define the pages that are sent back to the browser.

On the other hand, the Visual InterDev approach can be hard to manage if you're developing a large Web site, particularly if the site is constantly changing. Since all your presentation tier code is defined and deployed in text files, it's harder to find effective reuse techniques. You don't have an object-oriented mechanism by which you can encapsulate various parts of your logic from other parts. Instead, each page can become a smorgasbord of page content, layout details, code for dealing with user input, and calls to business objects.

The most common reuse technique for the Visual InterDev developer is to call Save As on an .ASP file and then customize the copy. This approach makes it pretty easy to change one page on the site. However, larger, site-wide changes can be more difficult. For example, supposed you need to slightly change the layout of a commonly used table report. If you have many .ASP files with redundant attribute settings for this report, you have to modify every page to accommodate this site-wide change. As you can see, this problem compromises your site's maintainability.

For smaller Web sites, this might not pose a huge problem. But with large sites, it's often necessary to change many .ASP files to add a new feature or modify the behavior of some client-side script. As you can see, this approach can compromise extensibility as well as maintainability.

Another disadvantage of larger ASP pages is that they can be slow. Because of the interpretive nature of script, larger ASP pages can't run as fast as compiled code. Moreover, every call that an ASP script makes to a COM object goes through IDispatch and uses late binding. This means that calls to business objects and calls to the built-in ASP objects are much slower than the same calls made from inside a compiled Visual Basic DLL. The performance degradation of late binding can be significant when a single ASP page makes hundreds or thousands of COM calls.

Creating the User Interface with Compiled Components

If you want to generate part or all of an application's user interface using Visual Basic components, you probably have to program against the ASP objects. It's important to note that you can do just about anything in an ActiveX DLL that you can do in an ASP page. You can thus write components that retrieve values from query strings and HTML form input controls using the Request object. You can use the Response object to write HTML and client-side script back to the browser. If you're familiar with the ASP object model, you know that there's a whole world of possibilities.

Let's look at what you have to do to program directly against the built-in ASP objects from Visual Basic components. First, you must reference both the COM+ Services Type Library and the Microsoft Active Server Pages Object Library in your ActiveX DLL project. Next, you retrieve ASP object references by name from the Item collection of the ObjectContext interface. The ASP objects that are available in the Item collection include Request, Response, Session, Application, and Server. It's that simple.

Look at the following method implementation:

 Sub MyMethodCalledFromASP() Dim rsp As Response Set rsp = GetObjectContext.Item("Response") rsp.Write "Hello World!" End Sub 

This code works the way it does because of integration between the ASP runtime and the COM+ runtime. When a server-side script in an ASP page creates an object from a configured component, the ASP runtime passes the references for these five built-in ASP objects to the COM+ runtime. The COM+ runtime uses these references to populate the Item collection when it initializes the new object's context. This is just another example of how the COM+ runtime environment flows contextual information from the creator to a newly created object. After the object is initialized, the ASP objects are available for the duration of the ASP request.

Each configured component has an IISIntrinsics attribute that must be set to True in order for its objects to access the built-in ASP objects. Fortunately, the default value for this attribute is True. (The COM+ documentation incorrectly lists the default value as False.) You should also note that you can't configure the IISIntrinsics attribute using the Component Services administrative tool. You must adjust it programmatically. Of course, you don't have to change it in order to write the code just shown. However, you can perform an optimization by setting the value to False for configured components that don't program against the ASP objects.

At this point, I'd like to make two important observations about Visual Basic components that use built-in ASP objects. First, ActiveX DLLs that use the ObjectContext interface to retrieve ASP references must program against the COM+ Services Type Library and should therefore be deployed as configured components. Second, a Visual Basic object requires a call to the ASP runtime each time it accesses an ASP object. If a Visual Basic object and the ASP page that created it live in different processes, this out-of-process call will be expensive.

The key point is that a Visual Basic component that uses ASP objects must be deployed in a COM+ library application as opposed to a COM+ server application. Otherwise, your code's performance will be unacceptable. During development, when performance isn't critical, it's fine to test and debug a component that uses ASP objects in a COM+ server application or in the Visual Basic debugger. But once your code is in production, the component must be added to a COM+ library application so that its objects will run in the same process as the ASP page that creates them. As I stated earlier in this chapter, you can run ASP pages together with Visual Basic objects in three ways: in INETINFO.EXE, in an isolated IIS application, or in the pooled IIS application.

Creating a custom framework for generating a user interface

If your goal is to maintain as much logic as possible inside compiled components, you can adopt a favorite strategy of developers who wear their "COM Is Love" T-shirts day after day. They believe that all application logic should be packed into COM-style DLLs. For the purpose of this discussion, allow me to label such developers as COM fanatics. These COM fanatics believe that ASP pages are evil because they aren't distributed in a compiled binary form. COM fanatics make a concerted effort to minimize what goes into ASP pages on their sites. They've discovered a way to minimize an entire Web site to a single ASP page:

 <% Dim ProgID, req ProgID = "WebFramework.ClientRequest" Set req = Server.CreateObject(ProgID) req.ProcessRequest %> 

Let's say that this ASP script relies on a custom component named ClientRequest, which is built into an ActiveX DLL project named WebFramework. The component exposes a single public method called ProcessRequest. This method serves as the sole entry point into a Web application based on the COM fanatic's custom framework. In this framework, the ProcessRequest method services each client request. Take a look at the following pseudocode:

 Sub ProcessRequest() ' Determine what command the user wants. ' Instantiate and call business objects. ' Create HTML with content and layout. ' Send HTML back to browser. End Sub 

The COM fanatic must devise an application design that allows clients to run any of the various commands that the application offers. However, all the requests come through a single entry point. How does the ProcessRequest method determine which command to run?

One popular technique is to pass the client's command preference in a query string. This requires some extra work. You must append the proper query string to your URLs as you dynamically write them into your pages. For instance, you can write your URLs to take the following form:

 MyPage.asp?Command=GetCustomerList 

Listing 9-1 is a sample implementation of ProcessRequest. This code interprets the client's request by pulling the command value out of the query string. It also shows a simplistic way to structure code to generate and transmit HTML back in the response. This is one possible starting point for creating the COM fanatic's framework. Companies typically try an approach such as this when they begin putting together a custom Web-based framework. Their goal is to achieve higher levels of reuse, maintainability, and extensibility. However, putting together a custom framework that meets these goals requires a significant investment at the beginning of a project. You also have to tackle many other design issues along the way.

Listing 9-1

 Sub ProcessRequest() Dim req As Request Set req = GetObjectContext("Request") Select Case req("Command") Case "", "GetStartPage" GetStartPage Case "GetCustomerList" GetCustomersList Case Else ' Handle unknown command. End Select Set req = Nothing End Sub Private Sub GetStartPage() ' Generate HTML for start page. End Sub Private Sub GetCustomerList() ' Create business object. ' Run query to retrieve customer data. ' Generate formatted HTML from customer data. End Sub 

Some companies spend lots of money trying to design and implement a custom framework before abandoning this approach and deciding that it's more cost-effective to go back to using ASP pages to define the user interface. If you decide to create such a framework, don't underestimate the up-front costs and the importance of a well-thought-out design.

Here are a few more things to think about. When you move to a component-based framework like this one, it's harder to use productivity-oriented page designers such as Microsoft FrontPage and Visual InterDev. If you do use a page designer, you usually can't use .ASP or .HTM files. You have to cut and paste snippets of HTML code into a database and then use these HTML snippets to parse together Web pages dynamically.

Another thing you should avoid is compiling any content or HTML layout details into your DLLs. For instance, if you define all your HTML layout tags in your DLL, you must recompile and redistribute your code whenever you want to change a minor cosmetic aspect of your site. Since you're trying to improve your site's maintainability with the framework, something's wrong if your framework creates new maintenance problems that you didn't have when the user interface was defined in ASP pages.

To achieve the highest levels of maintainability and extensibility, you should create a framework that uses a data-driven approach. You definitely want your application's view of business data (such as a customer list) to be data-driven, but you can take it much further. You should also strive for a data-driven approach when you define such things as page titles, page formatting, and navigation. This sort of data isn't exactly business data. It's metadata that the user interface portion of your application uses to do its job.

If you use a data-driven approach, you can create a framework that allows the site's Webmaster to add new pages by simply adding a new record to a database that holds your metadata. For example, you can create a database table named Pages that defines a set of fields such as Title, Header, and Body. The code in your framework can dynamically parse these elements into a Web page at runtime.

Likewise, you can easily make a site-wide change to such things as page formatting and the navigation toolbar if the metadata that defines them also lives in the database. If you get to a point where you can make site-wide formatting changes and add new pages without recompiling any code, you've done a good job.

As I've mentioned, if you take a data-driven approach, you should store HTML metadata and client-side script in a noncompiled medium. A database is usually the best choice. The framework can retrieve the metadata from the database at application startup or on an as-needed basis.

Let's say you decide to store all the HTML metadata in a DBMS such as Microsoft SQL Server or Oracle. When your ASP application starts, you can retrieve all your metadata from the database and load it into ASP Application variables. This will provide fast and easy access to metadata and let you quickly generate custom pages on the fly.

Using a Mix of ASP Pages and Components

The choice between ASP pages and Visual Basic components isn't an all-or-nothing proposition. Many companies find that the best balance is to use ASP pages to define the basic skeletons of their pages and to use components to generate the more tedious or processor-intensive aspects of the user interface.

Here are a few examples of what's possible. You can create a generic component that generates an HTML form with a set of input controls by inspecting the schema of a database table at runtime. You can create a custom Visual Basic component that creates formatted HTML tables by looping through an ADO recordset. If you're really progressive, you can write a component that leverages an XML parser to convert ADO recordsets into presentable HTML content.

As you can see, you have to consider quite a few issues when you decide how much user interface logic to put in ASP pages versus Visual Basic components. You also have to analyze the requirements of the project and assess the skills of your team members.



Programming Distributed Applications with COM+ and Microsoft Visual Basic 6.0
Programming Distributed Applications with Com and Microsoft Visual Basic 6.0 (Programming/Visual Basic)
ISBN: 1572319615
EAN: 2147483647
Year: 2000
Pages: 70
Authors: Ted Pattison

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net