Those of you who have built ASP applications with middle-tier components have come across the need to pass information from an ASP page to a component and then back to the ASP page. In Visual Basic (VB) there are currently two approaches that can be used to pass information across the layers. The first is to pass information from an ASP page to the component via the parameters of a function by value (ByVal) and then accept information back from the component via the function's return value. The other is to pass information into the component by reference (ByRef) and enable that information to be modified directly.
This latter approach is sometimes preferred because it allows a series of parameters or objects to be passed around and modified in a single method call, in contrast to using the return value of a function where only one object or parameter can be returned. However, unlike programming inside a complete VB system, when using ByRef with ASP and COM, a complication arises because ASP's VBScript is not typed, but the component's VB is typed. This article will briefly explain how ByRef can be used with ASP and COM.
The Code
Passing variables or objects around "by reference" is an important programming strategy. With "by reference," the caller gives the procedure the ability to access the caller's data and to modify that data. With "by value," a copy of the variable is passed, which means the procedure cannot modify the caller's data. As an example, consider the following code inside a VB program:
Dim X As Integer
Dim Y As Integer
X = 2
Y = 5
Call TestSub(X, Y)
Public Sub TestSub(ByVal X As Integer, ByRef Y As Integer)
X = X + 1
Y = X + 1
End Sub
Call MsgBox("Y = " & CStr(Y) & ", X = " & CStr(X))
The result of "TestSub(X, Y)" is Y equals 8 and X equals 2. Now, imagine the same procedure inside a class, say clsTest, of a VB component, say Test:
Public Sub TestSub(ByVal X As Integer, ByRef Y As Integer)
X = X + 1
Y = X + 1
End Sub
And, imagine the following on an ASP page, trying to invoke the above procedure TestSub:
Dim X, Y
X = 2
Y = 5
Dim objTest
Set objTest = Server.CreateObject("Test.clsTest")
Call objTest.TestSub(CInt(X), CInt(Y))
Response.Write(Y)
When Internet Information Server (IIS) attempts to load this page, notice that the lines "Call objTest.TestSub(CInt(X), CInt(Y))" and "Response.Write(Y)" will not produce the expected 8, but rather a "Type Mismatch error." What's more, this type mismatch error arises despite the CInt()'s. The problem, in my experience with IIS 4 (and most likely it applies for IIS 5 as well), is not so much that the variable going into the component cannot be understood, but that the modified value cannot be recognized by the ASP page.
One obvious solution here is to make TestSub into a function and return Y as its return value. However, if the goal is to pass, for example, two recordsets into the procedure and have those recordsets modified by the procedure, then there is no option but to use ByRef. (For one thing, objects must always be passed in by reference and also two arguments cannot fit into a single return value.) To illustrate a recordset example where a type mismatch occurs, consider the following procedure within a VB component:
Public Sub ModifyData(ByRef rstOne As ADODB.Recordset, ByRef rstTwo As ADODB.Recordset)
'code that modifies the data in both recordsets
End Sub
And let's say the ASP page is:
Dim rstOne, rstTwo
Set rstOne = Server.CreateObject("ADODB.Recordset")
Set rstTwo = Server.CreateObject("ADODB.Recordset")
Dim objTest
Set objTest = Server.CreateObject("Test.clsTest")
Call objTest.ModifyData(rstOne, rstTwo)
Here, despite the instantiating of the recordsets on the ASP page before they are passed into the component, the problem still occurs.
Fortunately, there is a way around it. The answer is to dimension a local variable or instantiate a local object, use that variable or object within the component, and then set the variant argument to equal the local variable or object just before the procedure ends.
'With a recordset
Public Sub ModifyData(ByRef varOne As Variant, ByRef varTwo As Variant)
Dim rstOne As ADODB.Recordset
Dim rstTwo As ADODB.Recordset
Set rstOne = varOne
Set rstTwo = varTwo
'code that modifies the data in both recordsets, rstOne and rstTwo
...
Set varOne = rstOne
Set varTwo = rstTwo
Set rstOne = Nothing
Set rstTwo = Nothing
End Sub
'With a variable
Public Sub TestSub(ByVal X As Integer, ByRef Y As Variant)
Dim intY as Integer
X = X + 1
intY = X + 1
Y = intY
End Sub
With this strategy, using ByRef with ASP and VB COM becomes possible because the type mismatch error is avoided.
When errors occur on a Web site, they should be handled in a way that helps the user to get back on track. Unfortunately, setting up customized error pages in IIS usually requires something many Web developers lack -- access to and familiarity with the Web server's administrative interface. With CustomError for IIS, developers can add error pages, coded by hand or created in their favorite editor, by simply uploading them to a designated directory. No administrator intervention is required.
Automatic daily builds is a well known software engineering best practice. This article introduces a strategy for implementing and promoting daily builds and offers tips and tricks for preventing and fixing breaks. [Read This Article][Top]
Building an application can be more than pressing F5. With an increasing
number of quality packages being released, developers for the .NET platform now have options to create a very sophisticated build process. Aaron Junod describes a sample build environment and shows how a number of tools can work together to make reliable, predictable, and value-added builds. [Read This Article][Top]
This short article provides source code for a classic ASP online database functions testing application and shows how to configure and use the tool for either SQL Server or Oracle. [Read This Article][Top]
One of many improvements ASP.NET brings to the development table is in error handling. Adam Tuliper whips up a simple ASP.NET solution for handling those pesky and unexpected post-production errors. [Read This Article][Top]
Mansoor Ahmed Siddiqui explains debugging and tracing and shows how to create custom
trace listeners to help ensure hassle-free development. [Read This Article][Top]
Firing events on a Web server is an easy task. However most of the easy solutions require you to have your own dedicated IIS or SQL Server on the Internet to play with, a privilege not shared by many. In this article, Matthew Muller shows you how to get the same functionality in a shared hosting environment.
[Read This Article][Top]
The script in Mark Newlands' article this week handles how errors are displayed and logged. It can capture all values in use at the time (e.g. form, querystring, session,and application level) and records them if you set a Boolean value to do so - displays custom HTML if required. Sends email, logs to database, and/or text file. [Read This Article][Top]
Transact-SQL provides developers with several database error-handling methods. Use these functions to efficiently handle database errors and add an extra level of data validation. This article discusses the @@ERROR, SP_ADDMESSAGE, and RAISERROR functions and provides examples on how to implement them.
[Read This Article][Top]
Read what advice members of the 15Seconds Discussion list had to offer on forcing pages to refesh, even when the user hits the back button.
[Read This Article][Top]
Mailing List
Want to receive email when the next article is published? Just Click Here to sign up.