Implementing Presentation Layers

Let's turn our attention now to some specific techniques you can use to implement your presentation layer applications. This is by no means a comprehensive discussion of all the techniques you will use to implement your applications. It does, however, cover the primary techniques you use to work with business objects.

Using Business Objects

First let's look at how you use business objects from applications running on user machines. We'll assume that the user machine can communicate with servers via DCOM and that the user machine is properly configured so that COM can locate the server machine on which a component is located.

Using business objects from Win32 applications

For native Win32 applications, the mechanics of accessing remote business objects really aren't much different from those for using any other COM component. You simply call CoCreateInstance, CoCreateInstanceEx, or the equivalent object creation mechanism provided by your development language. Once you've created an object, you make method calls as usual.

Note that you do not use the object context's CreateInstance method to create remote business objects from applications running on user machines. These applications are base clients, running outside the MTS environment. You need to use the object context's CreateInstance method only when you create MTS-hosted objects from within the MTS environment.

Recall from Chapter 4 that base client applications should acquire and hold pointers to MTS objects rather than re-creating the objects each time they are needed. One of the reasons for doing this is to avoid the expensive process of locating the remote server and establishing the communication session between the machines. Typically, an application will create objects during application initialization or when a specific portion of the application is first accessed. The interface pointers returned from object creation should be stored in application variables for future use. The pointers don't need to be released until the application shuts down, unless the application receives a communications error during a method call. A communication error might indicate that the remote server machine is unavailable. By releasing and reacquiring the interface pointer, you will be able to take advantage of MTS fail-over support on the server.

Using business objects from Web pages

From a Web page, you have two ways to create COM objects: by using the HTML <OBJECT> tag or by using client-side script code. The <OBJECT> tag is used to create objects as the page is rendered. This technique is normally used for visual objects, such as ActiveX controls. With script code, the objects are created only when the script is executed. These mechanisms work for both client-side and remote COM objects. In order to call methods on objects, regardless of how the objects were created, you'll need to write client-side script code. From the script code, you have access to methods and properties exposed by the IDispatch interfaces of your objects.

To use the <OBJECT> tag, you need to specify the CLSID of the business object and give it an ID so that you can access the object from your client-side script code. The following <OBJECT> tag could be used to create an instance of the Island Hopper bus_CustomerC.Customer component:

 <OBJECT ID="objCustomer"     CLASSID="clsid:6FED8869-EAC5-11D1-80F4-00C04FD61196"> </OBJECT> 

The exact script code you use to create objects depends on the scripting language you are using. In VBScript, you use the CreateObject function, as shown here:

 <SCRIPT LANGUAGE="VBScript">    Dim objCustomer    Set objCustomer = CreateObject("bus_CustomerC.Customer")    .    .    .    Set objCustomer = Nothing </SCRIPT> 

In Microsoft JScript, you use the ActiveXObject object, as shown here:

 <SCRIPT LANGUAGE="JScript">    var objCustomer;    objCustomer = new ActiveXObject("bus_CustomerC.Customer");    .    .    .    objCustomer = ""; </SCRIPT> 

Once the object is created, you can access its methods through script code, using the object ID as the variable name, as shown in the following example:

 <SCRIPT LANGUAGE="VBScript">    Dim rsCustomer    Set rsCustomer = objCustomer.GetByEmail("")    .    .    . </SCRIPT> 

Making business objects available to client machines

So far, we've assumed that the components were properly configured simply so that object creation would work. But what exactly is involved in configuring components for access from client machines?

To start with, you must either provide a CLSID and the remote server name in a call to CoCreateInstanceEx to create the object or install some information in the client machine's registry. To access components from Microsoft Visual Basic and most scripting languages, this information would include the ProgID, CLSID, and RemoteServerName registry entries. For business objects running in MTS environments, the easiest way to provide this information is to run the client install program discussed in Chapter 10 on each client machine. The client install program will also take care of installing and registering any type libraries or proxy/stub DLLs required in order to use vtable-binding or late-binding to access your components.

You can use the <OBJECT> tag on a Web page to download the client install program automatically using the Internet Component Download service. You use the CODEBASE parameter of the <OBJECT> tag to point the browser to a location where it can find the client install program. If you want to use Internet Component Download to automatically install the required registry entries for your remote component from a Web page, you must use the <OBJECT> tag to create the object; you cannot download and install component information from script code.

In addition to the normal registration, you will also need to consider code safety issues if your business objects will be used from Web pages. If you are using Internet Component Download, you will want to be sure that your install programs are signed with a digital signature. Depending on the user's browser settings, the browser might prevent unsigned install programs from being downloaded. The digital signature lets browsers determine the origin of the install program and detect whether it has been tampered with.

The Platform SDK contains information about and tools for creating signed packages for download. Some development tools, such as Visual Basic, also provide packaging and deployment tools that can be used to sign packages.

You should also mark your components as safe for scripting and initialization. This is usually a safe thing to do because your objects are not running on the client's machine. When you say a component is safe for scripting, you are telling users that client-side scripts can't use your component to harm their computers or obtain unauthorized information. When you say a component is safe for initialization, you are telling users that Web pages can't harm their computers by passing the component invalid data on initialization. The easiest way to mark your controls as safe for scripting and initialization is to add the following subkeys to the registry under your component's CLSID:

 Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4} 

If you don't mark your components as safe for scripting and initialization, the browser might elect not to create objects or make method calls to the objects, depending on the user's browser settings.

Using RDS to Access Remote Objects

Another option for accessing remote objects from client machines is by using RDS. RDS gives you the option of calling the objects via DCOM or via HTTP, which can be very helpful if you are accessing the remote objects from a Web page. One disadvantage of RDS is that it can be used to access methods only on the IDispatch interface exposed by your components. However, this limitation already applies to most scripting languages that you would use on a Web page.

To use your business objects with RDS over HTTP, you must add their ProgIDs to the ADCLaunch registry key on the server machine, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\ADCLaunch. To use the business objects with RDS over DCOM, you must mark them as safe for scripting and initialization, as described earlier. The client machine only needs a registry entry mapping the component's ProgID to its CLSID.

The RDS.Dataspace object is used to invoke your business objects. The following code fragment shows how a Web page could create an Island Hopper bus_CustomerC.Customer object and call its GetByEmail method, using RDS over HTTP:

 <SCRIPT LANGUAGE="VBScript">    Dim rdsds, objCustomer, rsCustomer    Set rdsds = CreateObject("RDS.Dataspace")    Set objCustomer = rdsds.CreateObject("bus_CustomerC.Customer", _                                         "http://IHopper")    Set rsCustomer = objCustomer.GetByEmail("")    .    .    . </SCRIPT> 

The DataSpace CreateObject method is used to generate a client-side proxy that understands how to call methods on the object using IDispatch, either over DCOM or over HTTP. The first parameter specifies the ProgID of the object to create. The second parameter specifies the name of the server machine on which the object is located. This parameter controls whether the object is called over DCOM or over HTTP. If the machine name is specified using the form \\machineName, DCOM is used. If the machine name is specified using the form http://machineName, HTTP is used. HTTP Secure (HTTPS) is also supported.

For more information about using RDS, including sample code, refer to the Microsoft Data Access SDK documentation included in the Platform SDK. The white paper "Remote Data Service in MDAC 2.0" by Kamaljit Bath is another excellent source of information; this white paper is available from the MSDN Web site,

Using Data-Binding

We saw in Chapter 3 that RDS can also be used to return disconnected ADO Recordset objects to client machines. In Internet Explorer 4 and later, DHTML data-binding can be used to connect these Recordset objects to HTML elements on your Web pages. Using data-binding and client-side scripting, you can let users browse through the Recordset objects without accessing the Web server.

The data-binding support in Internet Explorer 4 is not specific to any particular type of data. Internet Explorer 4 will bind to any type of data for which there is a data source object (DSO). The DSO is responsible for transporting data between client and server machines, manipulating the data, and providing an object model for script access. The DHTML attributes DATASRC, DATAFLD, DATAFORMATAS, and DATAPAGESIZE are used to determine where the data comes from, what fields of the data are bound to which HTML elements, whether the data should be treated as text or some other data type, and how many records should be displayed on a page.

The RDS.DataControl object is a DSO for OLE DB Rowset objects and ADO Recordset objects. This component supports both two-tier and three-tier models for data access. In the two-tier model, information about the data source is embedded in the Web page and each client gets its own connection to the data source. In the three-tier model, business objects are used to return a disconnected Recordset to the client, which is then attached to a DataControl object. The following code shows how you could bind the Recordset returned from an Island Hopper business object to a DataControl:

 <!-- The RDS DataControl object --> <OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"          ID=dsoCustomer HEIGHT=0 WIDTH=0>  </OBJECT> <SCRIPT LANGUAGE="VBSCRIPT">     Dim objCustomer     Set objCustomer = CreateObject("bus_CustomerC.Customer")     Set dsoCustomer.SourceRecordset = _            objCustomer.GetByEmail("")     .     .     . </SCRIPT> 

Microsoft Visual Studio 6.0 also supports data-binding to ADO Recordset objects. You can use the ADO Data Control object to establish a connection between data-bound controls and a Recordset object. First you create an ADO Data Control object, and then you set its Recordset property to the Recordset object returned from your business objects. For each data-bound control on a form or in a dialog box, set its DataSource property to the ADO Data Control object. You can also attach the Recordset object directly to each data-bound control using the DataSource property.

Using ASP

The techniques we have discussed so far work only if you can use COM objects from your client-side presentation layer applications. If you can't use COM objects on the client side, you can use ASP to call your business objects from the server and return Web pages to the client.

In Chapter 5, we looked briefly at how ASP and MTS are integrated with Microsoft Internet Information Server (IIS) 4. However, we did not discuss how to use your business objects from ASP pages. The mechanics are really quite simple. ASP pages contain a combination of directives, script, and text. Directives and script are delimited using the characters "<%" and "%>". You can also use the <SCRIPT> tag to mark a block of server-side script. Anything that is not directives or server-side script is copied as is into the Web page returned to the client.

Remember that ASP page scripts are executed when a request for a page is received from the client. Objects created in the scripts exist only for the duration of page processing, unless they are explicitly saved in Session or Application variables. Saving objects in Session or Application variables might limit scalability or affect dynamic load balancing, so you should carefully consider the implications before saving objects. Just to be clear: you cannot create an object during ASP page processing and pass it back to the client machine.

Within the scope of a page, you can create whatever objects you need to perform the work of the page. In general, you should try to encapsulate as much business logic as possible in components rather than using script code to do the work. Your server-side script should focus mainly on calling business objects and creating the Web page to be returned to the client.

With IIS 4.0, ASP pages can be marked as transactional. The page processing defines the transaction boundary for all objects created by the page. If any object aborts the transaction, you can return an error page instead of the normal page that was requested. To mark a page as transactional, you use the TRANSACTION directive on the first line of the page, as shown here:


You can use the OnTransactionCommit and OnTransactionAbort events to return different information to the client depending on whether the transaction committed or aborted, as shown here:

 <%' Display this page if the transaction succeeds.     Sub OnTransactionCommit()        Response.Write "<HTML>"        Response.Write "<BODY>"        .       .       .        Response.Write "</BODY>"        Response.Write "</HTML>"        Response.Flush()    End Sub %> <%' Display this page if the transaction fails.    Sub OnTransactionAbort()        Response.Clear()        Response.Write "<HTML>"        Response.Write "<BODY>"        Response.Write "We are unable to complete your transaction."        Response.Write "</BODY>"        Response.Write "</HTML>"        Response.Flush()    End Sub %> 

Within a page, you use the Server CreateObject method to create objects. This ensures that your objects are created within the proper transaction context and that you have access to the ASP intrinsic objects, such as Response and Request. For example, the following code could be used to create an Island Hopper bus_CustomerC.Customer object and call its GetByEmail method:

 <%    Dim objCustomer, rsCustomer    Set objCustomer = Server.CreateObject("bus_CustomerC.Customer")    Set rsCustomer = objCustomer.GetByEmail("")    .    .    . %> 

If you need to abort a transaction from within server-side script, you can call the ObjectContext SetAbort method, as shown here:

 <%    Dim objCustomer, rsCustomer    Set objCustomer = Server.CreateObject("bus_CustomerC.Customer")    ' Verify that object was created.    If Err.Number <> 0 Then       strErrorMessage = strErrorMessage & _           ERROR_CREATING_BUS_CUST & "<BR>"       GetObjectContext.SetAbort       Err.Clear    End If    .    .    . %> 

Using Client-Side Components

Finally, just a few words about client-side components. Using client-side components is no different than using remote business objects. However, if you are developing components to be used from client-side applications, you need to pay special attention to the code safety and download issues described earlier.

If you want to let client-side applications use Internet Component Download to download and install your components, you should package your components in a self-installing executable or .CAB file, according to the guidelines in the Microsoft Internet Component Download documentation in the Platform SDK. The downloadable file should be code-signed so that users can verify that the file comes from a trusted source and has not been tampered with. You should include or reference all the DLLs your component relies on in the download package. For example, you will need to ensure that the correct versions of any language run-time DLLs are properly installed. Your development tool documentation should explain what DLLs are required by components generated by the tool and might explain how to package those components for download.

Regardless of whether the components are downloaded, you should verify that your components are safe for scripting and initialization. As mentioned, some browser configurations might not let unsafe components be created or scripted. You can use the registry entries discussed earlier in the section titled, "Making Business Objects Available to Client Machines" to mark your components as safe for scripting and initialization, or you can implement the IObjectSafety interface which is explained in the Platform SDK.

Designing Component-Based Applications
Designing Component-Based Applications
ISBN: 0735605238
EAN: 2147483647
Year: 1997
Pages: 98
Authors: Mary Kirtland © 2008-2017.
If you may any questions please contact us: