Page #77 (Chapter 11 - Using ActiveX DLLs from WebClasses)

Chapter 11 - Using ActiveX DLLs from WebClasses

Visual Basic Developers Guide to ASP and IIS
A. Russell Jones
  Copyright 1999 SYBEX Inc.

Testing ActiveX DLLs from a WebClass
At this point, you're probably confused. The best way to understand the problem is to duplicate it. This project uses a simple ActiveX DLL that exposes one class called CHello. The sole purpose of the CHello class is to write the word Hello back to the browser.
Create a new IIS project. Rename the project WCTestCOM. Rename the default WebClass WCTest and set the NameInURL property to WCTest as well. Save the WCTestCOM project.
Copy the following code into the WebClass_Start event. If you're typing the code, don't leave out the error-trapping code.
Private Sub WebClass_Start()
    Dim ch As CHello
    Set ch = New CHello
    On Error GoTo ErrWebClass_Start
    Call ch.WriteHello(Response)
ExitWebClass_Start:
    Exit Sub
ErrWebClass_Start:
    Response.Write Err.Number & "<br>" & _
        Err.Source & "<br>" & _
        Err.Description
    Resume ExitWebClass_Start
End Sub
  Note You will need to change the code several times to follow along with the text of this section. As I promised, this time you won't need to enter the code yourself—I've provided commented-out versions of the WebClass_Start event. Comment and uncomment them as needed to run the tests in this section.
You'll need to create an ActiveX DLL project for the CHello class. Add a new ActiveX DLL project to your workspace and rename it TestObjContext. Rename the default class CHello.
You'll also need to add some project references before you can run the project. Click the WCTestCOM project (the IIS project) in the Project Explorer, click the Project menu, select References, and check the TestObjContext project. Similarly, select the TestObjContext project, click the Project menu, select References, and add references to the Microsoft Active Server Pages Object Library and to the Microsoft Transaction Server Type Library.
The CHello class has one public method called WriteHello that prints a Hello… message to the browser, with one optional argument called mResponse that accepts a Response object. Inside the WriteHello method, the CHello class calls getObjectContext in an attempt to get a reference to the ObjectContext object. It then tries to use the ObjectContext object to obtain a reference to the Response object:
Public Sub WriteHello(Optional mResponse As Response)
    Dim objContext As ObjectContext
    Set objContext = GetObjectContext()
    If Not objContext Is Nothing Then
        objContext("Response").Write _
        "Hello from ObjectContext Response"
    Else
        If Not IsMissing(mResponse) Then
            mResponse.Write "Hello from Response argument"
            Set mResponse = Nothing
        Else
            Err.Raise 50000, "CHello.WriteHello", _
            "Unable to obtain a reference to " & _
            "the Response object."
        End If
    End If
    Set objContext = Nothing
End Sub
Save the project and press F8 to step through it line by line. Notice that the WebClass explicitly passes a reference to the Response object in the argument to the WriteHello method. When the call occurs, the CHello class tries to get an ObjectContext reference. That attempt fails. Next, it tests to see whether the mResponse argument has been set. In this case, it has, so the mResponse.Write method executes successfully and you see Hello from Response argument in the browser.
The question is, why doesn't the call to getObjectContext work? You're running in a WebClass—an ActiveX DLL instantiated from an ASP page running in MTS—which does have an ObjectContext. You have a proper reference set to the ObjectContext object in the TestObjContext project. Everything should work, but it doesn't.
You might think (as I did), "OK, the WebClass doesn't have an ObjectContext, but the ActiveX DLL should be able to get one if I add it to an MTS package." I'll save you the trouble of trying it—that doesn't work either. You can get an ObjectContext object, but attempting to use that ObjectContext to obtain references to the intrinsic ASP objects fails.
This failure makes sense, because the WebClass doesn't have access to the ASP ScriptingContext object—remember, that's the one ASP object not passed to the WebClass from the launching ASP file.
As further proof that the failure stems from instantiating the CHello class from a WebClass rather than from any problem with the code itself, you can launch the CHello class from an ASP file and everything works perfectly. Create an ASP file called ASPHelloTest.asp containing the following code and save it in the WCTestCOM Web site:
<%
dim ch
set ch = Server.CreateObject("TestObjContext.CHello")
call ch.writeHello()
%>
When you run the ASP file, you'll see Hello from ObjectContext Response in the browser. Knowing that you can call the object from an ASP file makes things easier—just use the Server.CreateObject method from inside the WebClass to create the CHello object. Modify your WebClass_Start event code as follows:
Private Sub WebClass_Start()
    Dim ch As CHello
    Set ch = Server.CreateObject _
       ("TestObjcontext.CHello")
    On Error GoTo ErrWebClass_Start
    Call ch.WriteHello
ExitWebClass_Start:
    Exit Sub
ErrWebClass_Start:
    Response.Write Err.Number & "<br>" & _
        Err.Source & "<br>" & _
        Err.Description
    Resume ExitWebClass_Start
End Sub
Objects you instantiate by using the Server.CreateObject method from an ASP page are late bound, therefore slow. If you declare your objects in VB, however, they are early bound.
You will have no problems launching ActiveX DLLs that do not use the ObjectContext object from a WebClass. To prove this, comment out the objContext variable references in the WriteHello method as follows:
Public Sub WriteHello(Optional mResponse As Response)
    'Dim objContext As ObjectContext
    'Set objContext = GetObjectContext()
    'If Not objContext Is Nothing Then
    '    objContext("Response").Write _
    '    "Hello from ObjectContext Response"
    'Else
        If Not IsMissing(mResponse) Then
            mResponse.Write "Hello from Response argument"
            Set mResponse = Nothing
        Else
            Err.Raise 50000, "CHello.WriteHello", _
            "Unable to obtain a reference to " & _
            "the Response object."
        End If
    'End If
    'Set objContext = Nothing
End Sub
Change the code in the WebClass_Start method so you create the object with the New keyword, then compile the project and run it again.
How to Replace DLLs in IIS Applications
Before you can recompile a DLL used by an IIS application, you must shut down the application. If the DLL you're replacing runs inside MTS, you must also shut down that package. After compiling, you should refresh all the MTS objects to ensure that the references are correct. To avoid problems, use this sequence:
  1. Use the Internet Service Manager to unload the IIS application, then shut down the MTS package.
  2. Stop the IIS Administration site using either the Services applet or the IIS Stop icon on the WebClass toolbar.
  3. Recompile the WebClass and/or any support DLLs.
  4. Refresh the MTS package.
  5. Restart IIS.
If you don't follow this sequence, IIS and MTS often get "confused" and your project may not run properly. If this happens to you, my advice is to reboot the server.
You'll see the Hello from Response argument message properly printed in the browser. Therefore you can use the New keyword to access an ActiveX DLL from a WebClass as long as you don't try to get an ObjectContext reference.
Now let's look at the authentication problem. Uncomment the code from the WriteHello method again. You can use either of the WebClass_Start versions; it doesn't matter whether you use the one that instantiates the CHello object with New or with Server.CreateObject. Compile the WebClass project, close VB, and browse to the starting ASP file in a new instance of your browser.
When you launch the compiled WebClass DLL, the CHello object will not instantiate. That's because you don't have permission to use the object. As I said at the beginning of this chapter, the WebClass can't create the object because it can't authenticate with DCOM. You can move the CHello class into the WebClass project, and it will work fine.
The solution to the authentication problem is to move the CHello component into MTS. I'm not going to show you how to do that right now—you can skip ahead to Chapter 12, "IIS Applications and Microsoft Transaction Server," if you want to know—but I wanted to tell you that there is a workaround.
Table 11.1 summarizes the problems discussed in this chapter so far, and their workarounds.
Table 11.1: WebClass ObjectContext and Authentication Problems and Workarounds
Problem
Workaround
Obtain ObjectContext reference from WebClass
Run WebClass in MTS
Use ObjectContext reference in ActiveX object methods to gain access to intrinsic ASP objects
Use Server.CreateObject method or pass ASP objects or values explicitly
Authenticate DCOM calls successfully
Run ActiveX components in MTS
Now that you know how to work around the problems, you should be able to use ActiveX classes in separate DLLs freely. Many desirable class functions are not program specific; you can use them in multiple projects, so you wouldn't want to compile them into your WebClass DLL. Also, frankly, isolating these components is a good idea because it usually forces you to make them more generic, thus increasing code reuse.
Be careful of overusing ASP object references inside your ActiveX classes. For example, when you use the Response object inside an ActiveX class, that class is useless outside of a Web application. In contrast, if you pass a string back from the object and use the Response object inside the WebClass to print the string to the browser, you can use the object from ASP pages, from WebClasses, or from stand-alone executables in exactly the same way.
Here's an example: In Chapter 8, "Maintaining State in IIS Applications," the StoredRecordset class exposes an HTMLTableString property.
Name
Type
Description
HTMLTableString
Property Get
Returns the stored recordset formatted as an HTML table string
The property returns a string containing an HTML-formatted table. The class works from ASP, from WebClasses, and from stand-alone executables. If, instead, I had used getObjectContext to obtain a reference to the Response object with which to print the string from inside the class, it would work only with Web applications.



Visual Basic Developer[ap]s Guide to ASP and IIS
Visual Basic Developer[ap]s Guide to ASP and IIS
ISBN: 782125573
EAN: N/A
Year: 2005
Pages: 98

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