Active Server Pages |
Introduced in 1996, Active Server Pages (ASP) is an easy to learn server-side technology from
Microsoft that has taken the web by storm. ASP is implemented as a set of objects with built-in
features for fast and simple access to common services provided by the web-server for the Internet.
As we will see, there are versatile reasons for using ASP as a server-side technology with
ActivePerl.
To begin, if you in general are unfamiliar with server-side technologies, let's start at the core by
describing the need-to-know about ASP. ASP is a feature that installs with Microsoft's Internet
Information Services (IIS) web-server. No special interaction or configuration is needed afterwards,
and it should run out of the box just as easily as IIS. Fundamentally, a server-side technology such
as ASP puts no requirements on the client or browser, and, as a result, no browser-compatibility
issues will ever occur, no browser plug-ins have to be installed, and the client does not need a
local installation of ActivePerl.
Since there are no client requirements for ASP, it needs something on the server-side that tells it
what to do with its features. A special implementation of a scripting language is therefore
installed on the server and used in order to control and program ASP; PerlScript, which installs
with ActivePerl, is suitable for the role as scripting language because it brings the power of Perl
into the environment of ASP and there merges it with the services provided by ASP. There are only
two things that you either may already know or will need to learn while using PerlScript:
On the Internet, ASP serves documents of its own filetype as opposed to familiar document types
like HTML documents. This is so that the ASP document can be processed on the server side before
returned to the client's browser. An ASP document has the file extension .asp, and it provides both
existing features derived from ASP and the ability to execute script commands within the document.
The file extension is by the webserver recognized in a special way which results in the underlying
technology executing script commands that are within the file and treat other markup such as HTML in
a standard fashion. The source code of your saved file's PerlScript script commands will by default
never be available to the user when choosing to view the document source in the browser, so any
script that you write can not be copied. The reason for this is because everything is processed on
the server side and what is returned to the browser is a standard format such as HTML.
For a closure, it deserves to be repeated that if you are unfamiliar with object-oriented
programming in Perl, it is strongly recommended that you sometime browse the Perl documentation on
object-oriented programming to get a basic understanding of the aspects of an object and its origin.
Next up, let's look at how to embed PerlScript commands within an ASP document.
The Script Delimiters
To successfully execute the script commands within an ASP file, you must specify what scripting
language ASP should use to interpret the script commands. You can do this within the .asp document
by either setting a default scripting language in which all script commands within the
script-delimiters <% and %> will be executed by the specified scripting language. Either you
can apply that setting that within the Microsoft Management Console's IIS snap-in or you can use
what ASP recognizes as a page command, which is indicated by the special directive @. The following
example is for illustrational purposes only and it shows you how to set the default scripting
language for the ASP file to PerlScript; as a result, all commands will be treated by the PerlScript
engine; however, please note that no actual output or result is being displayed by the script, so if
you run the code shown in the example below, you won't see an output although the code is being
executed and interpreted.
<%@ Language=PerlScript %>
<%
for($i=0; $i<=10; $i++) {
#
# Your Perl code here
#
}
%>
In addition to page-commands, you can set the scripting language for a defined scope by using the <SCRIPT
Language=PerlScript RUNAT=Server>
and </SCRIPT>
delimiters. This
results in the scripting language only executing the code within the <script> elements
regardless of what the default scripting language is set to for a language by the webserver or by an
ASP page command for the current document.
<SCRIPT Language=PerlScript RUNAT=Server>
for($i=0; $i<=10; $i++) {
#
# Your Perl code here
#
}
</SCRIPT>
The Scripting Host
When Active Server Pages acts as the scripting host for PerlScript, it is initalized as a host first
when an ASP file on the web-server is requested by the way of a URL (such as http://www.domain.com/home.asp).
The web-server locates the file, and the scripting host locates the script commands that are within
the script delimiters. The chunks of code found within the delimiters are passed on to PerlScript,
which creates a Perl interpreter that treats the code. Afterwards, it returns to the scripting host,
which waits for the next incoming call. Certain rules apply to when you write code to interact with
scripting hosts such as ASP, and let's look at one of those necessary things to know by illustrating
it as a parallel to writing a command-line Perl script. When you began programming Perl, among the
first things you probably learned was how to print text to the screen, and it is not unusual that
such a script looks as follows.
As seen, the print "Hello World";
"print()"
-function of Perl outputs the string "Hello
World" to what is known as the Standard Output. PerlScript, too, will send any output to what
it knows as Standard Output, and when executed within the ASP scripting host, the PerlScript engine
will use the features of the host's object-model in order to reach the standard output. Essentially,
the host provides a set of features, and you pick the scripting language in which you wish to write
your application to interact with the host. In ASP, you need to know the host because it decides
what method and what object you need to deploy of the host's in order to output a string. A
scripting language would become extremely bloated if it had to keep track of all those things In
contrast, the scripter needs to keep track of such features. :-) To send "Hello World" to
the client's browser by using ASP, you call the "Write()
"-method of the
Response object as in the next example.
In essence, it is of most importance that you know the object-model of the ASP scripting host within
which you use PerlScript so that you know what object to call and how to get the best performance
out of your application.
$Response->Write("Hello World");
<HTML> Hello World </HTML>
"<%@Language=PerlScript%>
<HTML>
<TITLE> PerlScript Test </TITLE>
<%
for($i=0; $i<=10; $i+=2) {
$Response->Write("<FONT SIZE=$i COLOR=#000000>");
$Response->Write("Hello World! </FONT> <BR>");
}
%>
</HTML>
Write()
"-method
sends the HTML and variable value of $i
to the browser. However, $i
is a
part of the HTML Font element, so the result is that the font size is increased by 2 for each time
"Hello World" is sent to the client's browser. You could also write the script this way:<HTML> <TITLE> PerlScript Example </TITLE> <script language=perlscript runat=server> for($i=0; $i<=10; $i+=2) {
$Response->Write("<FONT SIZE=$i COLOR=#000000>"); $Response->Write("Hello World! </FONT> <BR>");
} </script> </HTML>A closure to this example, there is a shorthand for writing
$Response->Write($variable)
,
and it is not available when already within script delimiters; however, to easily mix variables with
HTML you can automatically call the mentioned method by <%=$variable%>
where the
equal-sign automatically translates into $Response->Write()
. For example:<HTML> <TITLE> PerlScript Example </TITLE> <% @Language=PerlScript %> <% for($i=0; $i<=10; $i+=2) { %> <FONT SIZE=<%=$i%> COLOR=#000000> Hello World! </FONT> <BR> <% } >% </HTML>
Providing an interface to common tasks for a web programmer, ASP simplifies web-programming by
making the simple tasks even easier. The features of ASP are implemented and exposed as objects,
and, in addition, a scripting language is enabled to not only use those features of the ASP host,
the language can certainly use its own features, too.
# Set an application variable
#
$Application->Contents->SetProperty('Item', 'myName', 'Tobias');
# Access an application variable
#
$Application->Contents->Item('myName');
# Return the ASPError object
#
$ASPError = $Server->GetLastError();
# Output the error's description
#
$Response->Write( $ASPError->{Description} );
@TRANSACTION
page
command in the page, whereas you are enabled only to define @ once per file; however, you can use
multiple directives within the @ such as <%@directiveA=something directiveB=somethingelse%>
.
If you use PerlScript a lot, you are better off setting it as the default language in the Microsoft
Management Console. Setting the default language in the MMC is unfortunately not an option for
Personal Web Server. PWS is good for practicing a scripting language and ASP, but it is not good for
tailormaking your webservice in terms of IIS applications and other tasks that are administrative.
For example, it does not have the Microsoft Management Console. What PWS mainly does is to allow you
to publish and develop Active Server Pages within reson while it hides the administrative tasks.TotalBytes
-property and then read it with the BinaryRead($bytes_to_read)
method.
# Get the number of total bytes in the request
#
$bytes_to_read = $Request->{TotalBytes};
# Read and return a variant array of type VT_U1
#
$read_bytes=$Request->BinaryRead( $bytes_to_read );
ClientCertificate
for
digital certificated, Cookies
for cookies sent with the HTTP request, Form
for data posted by a web form using the POST method, QueryString
for data passed with
the QueryString or GET method from a web form, and ServerVariables
for HTTP environment
variables such as the server software or the users browser.
# Let's see what's in the ALL_HTTP variable
#
$Response->Write( $Request->ServerVariables('ALL_HTTP')->Item() );
# Ask the client's browser if it wants a cookie
#
$Response->Cookies->SetProperty(
'Item',
'someCookie',
'Hi! This is a cookie!'
);
# ==================================================
# Let's set some attributes of the cookie!
# ==================================================
# This is the domain that can read the cookie; to specify it further,
# use the Path-attribute to define a more complete URL
#
$Response->Cookies('someCookie')->{Domain} = 'somesite.com';
# The expiration date for the cookie
#
$Response->Cookies('someCookie')->{Expires} = 'January 1, 1999';
# Not a secure cookie; 1 defines it as secure
#
$Response->Cookies('someCookie')->{Secure} = 0;
Timeout
which defines for how many seconds a script should try executing before returning an error. This
setting can also be set in the Microsoft Management Console. In terms of methods, you can create
instances of COM objects in your page, encoding HTML and URL's, mapping the physical path to a file
by providing its URL, execute other .asp files, and seamlessly transfer the client to a new page
while maintaining the state of the current ASP objects, which means that any form data that was
gathered can be transferred between pages.
# Open the file in the virtual path /scripts/forum.asp/
#
open( FILE, $Server->MapPath('/scripts/forum.asp') );
CreateObject('ProgID')
to return a valid COM object to the Active Server
Page. For example, to instantiate an ADO object, you'd do the following:
# Create an ADO Connection object
#
$ADOConnObj = $Server->CreateObject('ADODB.Connection');
HTMLEncode($string)
encodes charaters such as greater than and less
than into its valid character represenation within an HTML page. This prevents, for example, users
to post HTML to a chatroom or messageboard. The URLEncode($string)
-method encodes a
string for valid represenation as a URL. New in IIS 5, you can Execute('/scripts/page.asp')
ASP scripts in other files, and to transfer the user without losing the state of the Request
object's existing variables such as the contents of the Form-collection you can use the
Transfer-method.
# Transfer the user to a different page
#
$Server->Transfer('/step2.asp');
Timeout
-property to the number of minutes that you wish the Session to last before
it is ended or you can deliberately end the Session by calling the Abandon
-method and
then redirect to a new page. The redirection is very important! Other properties that you can use is
CodePage
which is used for Symbol Mapping, LCID
for the locale identifier,
and SessionID
which uniquely identifies the client.Remove()
and RemoveAll()
method. Remove()
takes either an index or a keyname for
the variable in the Collection to remove, and RemoveAll()
removes all variables stored
in the collection. In example, consider that you have stores a property called "myName" in
the Session s Contents collection, you would remove it as follows:
$Session->Contents->Remove('myName');
Remove()
and RemoveAll()
are not available, so you
will have to use the Perl built-in function undef()
,.
The Active Server Pages Samples
The following examples are taken from the \eg\aspsamples\ directory, which will be installed on your
machine if you installed the example files with ActivePerl. In addition to these examples, there are
useful and advanced examples in the \eg\aspsamples\ directory.
Say "Hello World!"
File Location: [\eg\aspsamples\hello.asp]
In this example, a for-loop is used to print a series of "Hello World!" strings of
increasing font-size. Notice the <%=$i%>
call, which is shorthand for writing
$Response->write($i).
<%
for ($i = 3; $i < 8; $i++) {
%>
<font size=<%= $i %>>
"Hello World!"
</font>
<BR>
<%
}
%>
Accessing HTTP Server Variables
File Location: [\eg\aspsamples\srvvar.asp]
The HyperText Transfer Protocol (HTTP) variables that are sent with each request can be retrieved
from the Request object. You need to specify that you want the server variables, and then call a
method named "Item" in order to return the value.
<%= $Request->ServerVariables('SERVER_SOFTWARE')->Item() %>
Reading the QueryString
File Location: [\eg\aspsamples\qstring.asp]
The QueryString can be either manufactured by handcoding it, or it is automatically generated for
form-fields if you use a HTML form that uses the GET method for submitting its data. The following
is one way you can use it.
<A HREF="<%=$Request->ServerVariables('PATH_INFO')->item()%>?Size=Medium&Color=Yellow">
This link will demonstrate the Request object's QueryString collection.
</A>
The current value of Size is
<%= $Request->QueryString('Size')->item() %>
<BR>
The current value of Color is
<%= $Request->QueryString('Color')->item() %>
Interactive Web Forms
[\eg\aspsamples\wform.asp]
In this example, the POST method is used to submit a form. The Request object gathers data by
calling the Form-element by its name in $Request->Form('name')->Item()
instead of
in $Request->QueryString('name')->Item()
as it is passed when the method is GET.
Once fetched, the "$Server->HTMLEncode()
"-method is called to correctly
translate HTML tags into proper encoding so that no HTML tags can be submitted.
<%
my($name) = $Request->Form('Yourname')->Item();
$name = $Server->HTMLEncode($name);
%>
<%
if($name eq 'Enter Your name here') {
$Response->Write("Please type your name in the box below and then press the button");
}
else {
$Response->Write("Hello $name");
}
%>
<CENTER>
<FORM ACTION="wform.asp" METHOD="POST">
<INPUT TYPE="Textfield" NAME="Yourname" MAXLENGTH="30" VALUE="Enter Your Name Here">
<INPUT TYPE="SUBMIT" VALUE="Click Me">
</FORM>
</CENTER>
Database Connections (ADO and ASP)
[\eg\aspsamples\ado1.asp]
This database example requires the ActiveX Data Objects from the Microsoft Data Access Components,
available at http://www.microsoft.com/data/.
<% # Create an instance of the ADO Connection object # $Conn = $Server->CreateObject("ADODB.Connection"); # Open a system DSN # $Conn->Open( "ADOSamples" ); # Execute an SQL Query # $RS = $Conn->Execute( "SELECT * FROM Orders" ); # Read a property to get the number of columns # present in the Recordset returned from the # query. # $count = $RS->Fields->{Count}; # Print out the names of each column # for ( $i = 0; $i < $count; $i++ ) { $Response->Write( $RS->Fields($i)->Name ); $Response->Write("<BR>"); }; # Loop the Recordset until there are no more records # while ( ! $RS->{EOF} ) { for ( $i = 0; $i < $count; $i++ ) { $Response->Write(" "); $Response->Write($RS->Fields($i)->{Value}); $Response->Write("<BR>"); }; # Move to the next record # $RS->MoveNext(); }; # Close the Recordset # $RS->Close(); $Conn->Close(); %>
At times, you will be working with binary data that is passed to PerlScript from a COM object or
passed from PerlScript to a COM object. In Windows Script, the data comes in a data type called a
Variant. The Variant resembles of Perl's scalar variables because it was designed for holding most
types of data. And most of the time, Perl is able to determine what type of Variant that is being
returned to it from a COM object; however, with binary data, it sometimes becomes necessary to
define what the variant is exactly for a type, so the "Win32::OLE::Variant
"-module
provides functionality for this conversion and much more. For example, if you have a GIF image
stored in the variable $image
, and you want to output it to the screen by using the
Response object's "BinaryWrite()
"-method, you must convert it to a VT_UI1
variant before it is passed to the "BinaryWrite()
"-method simply because a
VT_UI1 variant is expected by the method.
use Win32::OLE::Variant; # Tell the browser a GIF image is on its way # $Response->{ContentType} = "image/GIF"; # Send the GIF as a VT_UI1 Variant # $Response->BinaryWrite(Win32::OLE->Variant(VT_UI1, $image));An issue of needing to convert to the accurate type of Variant occurs most of the time when working with binary data; two concrete examples are binary large objects (BLOBs) returned from SQL Server and binary data being output through the ASP Response object's "
BinaryWrite()
"-method.
The "BinaryWrite()
"-method expects a Variant of the type VT_UI1, and that is
the same type which is returned when reading a BLOB from SQL Server. However, as the variant is
returned to PerlScript, it converts it into the type of scalar that most resembles the variant, and
although that is an accurate conversion for use in Perl, you will need to convert data if it's used
in a VT_UI1 context.
The following example will demonstrate how ADO can be used to read a Binary Large Object from SQL Server, and how ASP is used to output the BLOB as an image.
<%@Language=PerlScript%> <% use Win32::OLE::Variant; # One note, 40 as bytes to read per GetChunk()-call is not # a good number to choose for a real application. I emphasize # _not_. Instead, whatever you choose depends much on your # system and the power of it; however, 4000 is a much more # realistic real-world number compared to 32. # my($blob_size, $read_size, $bytes_to_read) = (0, 0, 32); # Let's create the Connection object used to establish the connection # $conn = $Server->CreateObject('ADODB.Connection'); # Open a connection using the SQL Server OLE DB Provider # $conn->Open(<<EOF); Provider=SQLOLEDB; Persist Security Info=False; User ID=sa;Initial Catalog=pubs EOF # Execute the query which returns the BLOB from our database # $rs = $conn->Execute("SELECT logo FROM pub_info WHERE pub_id='0736'"); # Get the size of the BLOB # $blob_size = $rs->FieldS('logo')->{ActualSize}; # And here's the routine for reading in the blob. Alternatively you can # make a control statement that says if the $blob_size is less than # 4096, it should just swallow it in one chunk, but the routine below # is good to have handy # while($read_size < $blob_size) {
$buffer .= $rs->Fields('logo')->GetChunk($bytes_to_read); $read_size += $bytes_to_read; if($read_size+$bytes_to_read > $ blob_size) {
$bytes_to_read = $blob_size - $read_size;
}
} # Make a VT_UI1 variant of the retrieved Chunks # $image = new Win32::OLE::Variant(VT_UI1, $buffer); # Tell the browser that the content coming is an image of the type GIF # $Response->{ContentType}="image/gif"; # Do a binarywrite of the VT_UI1 variant image # $Response->BinaryWrite($image); %>
The System Data Source Name is information stored in the Windows-registry. The information is
used by your application to connect to a database. To create a SystemDSN you must have a database
ready to be used by your application and know the path to the database.When the information above is
gathered you open "32 Bit ODBC" from the control-panel andclick on the "SystemDSN"-tab.
Choose to "Add" a new SystemDSN and select the driver foryour database. Enter the
"Data Source Name" that you will call on the database by fromyour application, then click
on the "Select"-button and browse to your database-file.Okay everything, then close the
program. You'll now be able to call on your databaseby the Data Source Name you entered for it as
follows:
Appendix A
How To Set Up A System DSN
$Conn = $Server->CreateObject("ADODB.Connection");
$Conn->Open("Name");
With the ActiveX Data Objects (ADO), the layer that connectes to a database is called the OLE DB layer. It is the very closest to the physical database, and directly connecting to OLE DB is ADO. Most databases will have what is called an OLE DB Provider, and if you have worked with ODBC, the OLE DB provider is OLE DB's equivalent of the ODBC driver. In ADO, ideally you should connect via ADO directly to OLE DB and from OLE DB directly to the physical database or other data store. A System DSN is for ODBC data sources and it causes OLE DB to wrap an ODBC driver within itself, which adds an overhead and reduces performance.
There are a number of things you can do to get the native provider set up. When you have it set up, you simply replace the name of the system DSN with the string that has been produced in order to connect to the data store using the native OLE DB provider. First, try to create an Universal Data Link file by doing the following:
Provider=Microsoft.Jet.OLEDB.4.0;
User ID=Somebody;
Data Source=c:\\access.mdb;
Persist Security Info=False
Provider=SQLOLEDB;
Persist Security Info=False;
User ID=sa;
Initial Catalog=Northwind
Appendix B
Books Resources
ActivePerl with ASP and ADO:
by Tobias Martinsson
ISBN 0471383147
URL: http://www.wiley.com/compbooks/
Copyright (c) 2000 Tobias Martinsson. All Rights Reserved.
When included as part of the Standard Version of Perl, or as part of its complete documentation whether printed or otherwise, this work may be distributed only under the terms of Perl's Artistic License. Any distribution of this file or derivatives thereof outside of that package require that special arrangements be made with copyright holder.
Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.
Active Server Pages is copyright (c) Microsoft Corporation. All rights reserved.
Active Server Pages |