Baz
Baz

Reputation: 13145

Class not defined error when mixing scripting languages

The following code:

<%
Response.Write("VB comes second!")

'page1()
Dim p
Set p = New Page
%>

<script language = "Python" runat="server">
Response.Write("Python comes first!")

class Page:
    def display_top(self):
        Response.Write("""
        <html>
        """)

    def display_body(self, body_text):
        Response.Write("<body>"+body_text+"</body>")

    def display_bottom(self):
        Response.Write("""
        </html>
        """)

def page1():
    p = Page()
    p.display_top()
    p.display_body("This is my body!")
    p.display_bottom()
</script>

Gives the error:

Error Type:
Microsoft VBScript runtime (0x800A01FA)
Class not defined: 'Page'
/website/index.asp, line 6

But why?

If I call the function page1() from within the VBScript, then it works as expected.

Thanks,

Barry

EDIT 1:

This:

<script language = "Python" runat="server">
class Page:
    def display_top(self):
        Response.Write("<html>")
</script>

<%
Dim p
Set p = server.createobject("Page")
%>

Gives the error:

Invalid class string

If I use:

Set p = New Page

instead, then I get:

Class not defined: 'Page'

Upvotes: 0

Views: 3314

Answers (5)

Average Joe
Average Joe

Reputation: 4601

The problem is the order of execution. I don't have python installed on my server. So I did a test for you with JS vs VB - which is the same problem I referred to. Take a look;

<%
Response.Write "VBScript Here - 1 <p>"
%>

<script language=JavaScript runat=Server>
    Response.Write("Javascript here - 2 <p>");
</script>

<%
    Response.Write("VBScript here - 3 <p>")
%>


<script language=JavaScript runat=Server>
    Response.Write("Javascript here - 4 <p>");  
</script>

<%
    Response.Write("VBScript here - 5 <p>")
%>

will give you this

Javascript here - 2
Javascript here - 4
VBScript Here - 1
VBScript here - 3
VBScript here - 5

Upvotes: 0

Cheran Shunmugavel
Cheran Shunmugavel

Reputation: 8459

I can't find a definitive source for this, but I'm pretty sure that the VBScript New keyword can only be used to instantiate classes defined in VBScript using the Class keyword. What you should do instead is write a "factory" function in Python that will return a new Page object. Then you can call that function from VBScript.

I don't know Python, but here's an example with VBScript and JScript to illustrate the point:

<%
Dim p
Set p = makePage("hello")
Response.Write p.foo
%>

<script language="JScript" runat="server">
function Page(foo) {
    this.foo = foo;
}

function makePage(foo) {
    return new Page(foo);
}
</script>

Upvotes: 2

Average Joe
Average Joe

Reputation: 4601

Proof that the class defined in one script block is reachable from another script block; 

<%
Response.Write "VBScript Here - 1 <p>"
hello()

apple.color = "reddish"
response.write (apple.getInfo())

%>

<script language=JavaScript runat=Server>
    Response.Write("Javascript here - 2 <p>");
    function hello()
    {
        Response.Write("Hello from JS <p>");
    }


    var apple = {
        type: "macintosh",
        color: "red",
        getInfo: function () {
            return this.color + ' ' + this.type + ' apple' + '<p>';
        }
    }


</script>

<%
    Response.Write("VBScript here - 3 <p>")
%>


<script language=JavaScript runat=Server>
    Response.Write("Javascript here - 4 <p>");  
</script>

<%
    Response.Write("VBScript here - 5 <p>")
%>


will give you this 
Javascript here - 2
Javascript here - 4
VBScript Here - 1
Hello from JS
reddish macintosh apple
VBScript here - 3
VBScript here - 5

Upvotes: 1

Nilpo
Nilpo

Reputation: 4816

You need to reverse the script order. When your script encounters a function call, it allows that function block to be in any code block on the page within the same scope. This is not true when instantiating objects. While instantiating objects, the object code must be processed before the instantiating line. Scripting is for all intents and purposes executed linearly.

Upvotes: 0

Average Joe
Average Joe

Reputation: 4601

You are hitting a asp engine limitation right there.

Code in <script runat=server> blocks may run at different times.

Server Script Order of Execution

Inline server script runs sequentially, top to bottom. You can define callable routines (functions or subroutines) in server script, and they will be called as needed.

All inline script has to be in the same language namely, the language specified in the @ directive at the top of the page. Therefore, you can't mix scripting languages in inline script.

"But wait!" you might say. It is theoretically possible to put inline-like script into a <SCRIPT> element that is, have script in the element that is not part of a function or subroutine, as in the following example:

<% Response.Write("Some inline script<BR>")%>
<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
    Response.Write("Script in a SCRIPT element<BR>")
</SCRIPT>

Yes, you can do this. *However, you are then at the mercy of the order of execution of the IIS ASP processor.*

Ordering Script Blocks

When you are mixing languages, the order in which <SCRIPT> blocks appear in the page can make a difference as to whether they work properly. Consider this simple case of an inline VBScript script calling a function written in JScript:

<SCRIPT LANGUAGE="VBScript">
    ' Calls a JScript function
    aNumber = 2
    doubledNumber = doubleMe(aNumber)
    document.write("The answer is " & doubledNumber)
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
    function doubleMe(aNumber){
        return aNumber * 2;
    }
</SCRIPT>

This won't work. More specifically, the document.write statement will write an empty string to the page. Why? Because at the time the VBScript block is being processed, the following JScript <SCRIPT> block has not yet been read, parsed, and made available to the page. When the browser processes the script blocks in the page, it works from top to bottom.

In this case, simply reversing the order of the script blocks solves the problem. And in fact, this type of scenario is not all that common—for the most part, <SCRIPT> blocks contain functions and subroutines that will not be called until the page has been fully loaded and all elements are available. Nonetheless, you should keep in the back of your mind the fact that pages are processed linearly and that <SCRIPT> blocks in different languages are processed separately.

To learn more, pls visit this MSDN knowledge base article.

Upvotes: 1

Related Questions