Server Object |
The Server object provides several miscellaneous functions that you can use in your Active Server Page applications. Although most of its methods are esoteric and seldom used, three methods, CreateObject, Execute, and Transfer, and the Server object's single property, ScriptTimeout, are invaluable. You will use these in many of your scripts.

The Server object, as its name implies, represents the web server itself, and much of the functionality it provides is simply functionality the web server itself uses in the normal processing of client requests and server responses.

Comments/Troubleshooting |
Use of the Server object's property and methods is straightforward. Typically, if you are using the Server object's functionality with the correct syntax, you will experience the expected outcome. If you experience errors, it typically indicates a problem with IIS itself either in its configuration or in its installation.

ScriptTimeout |
Server.ScriptTimeout [ = lngNumSeconds]
Specifies the maximum amount of time the web server will continue processing your script. If you do not set a value for this property, the default value is 90 seconds.
Parameters

lngNumSeconds

  The number of seconds you want the web server to continue processing your script before it times out, sending the client an ASP error.

Example
    <%

    ' The following code sets the amount of time before the
    ' script times out to 100 seconds. If the script takes
    ' more time than 100 seconds, the script will time out and
    ' a timeout error will be sent to the client.
    Server.ScriptTimeout = 100

    %>
Notes
The number used in setting the ScriptTimeout property's value must be greater than or equal to that set in the AspScriptTimeout property in the IIS metabase or the setting will be ignored. For example, the default setting of AspScriptTimeout in the IIS metabase is 90 seconds. If you use the ScriptTimeout property to decrease this time to 10 seconds without first changing the setting in the metabase, the script will still time out after 90 seconds.

You should consider decreasing the AspScriptTimeout property in the IIS metabase. 90 seconds is a long time to wait for processing a web request. Show me a user who is willing to wait for a minute and a half, and I'll show you a user who has fallen asleep. However, if your application requires a longer timeout setting, consider using an interim "Please wait . . ." page whose OnLoad event will in turn call the longer script or ASP page. This will give the user some notice that her wait will be a long one.

This technique is demonstrated in the following code. Assume that you must call the InfoSearch.ASP script, and you know that it takes a single parameter, strSrchItem , and that it takes up to two minutes to complete its tasks. Instead of calling InfoSearch.ASP immediately, you could call the following page instead:

    <HTML>
    <HEAD><TITLE>Search Wait</TITLE></HEAD>
    <BODY LANGUAGE="VBScript" OnLoad = "PageLoad( )">
    Please wait, your request is being processed...
    <SCRIPT LANGUAGE="VBScript">
    Sub PageLoad( )
    Parent.Location.HREF = _
    "InfoSearch.ASP?<%=Request.ServerVariables("QUERY_STRING")%>"
    End Sub
    </SCRIPT>
    </BODY>
    </HTML>

As you can see, when this script loads, it calls the page with the long script, sending the original query string (retrieved from the ServerVariables collection of the Request object; see Chapter 7, for more details). This gives the user immediate feedback without forcing him to sit watching a blank screen waiting for a script to complete processing.

CreateObject |
Set objMyObject = Server.CreateObject(strProgId)
Instantiates an object on the server. Once instantiated, this object's properties and methods can be used just as you can use the properties and methods of the built-in objects that come with ASP. The DLLs from which these objects are instantiated must be installed and registered on the web server machine separately from your installation of IIS.
Parameters

objMyObject

  The name of a variable that will contain a reference to the object you are instantiating.

strProgId

  The programmatic ID for the class from which you would like to instantiate an object. The format for the strProgId parameter is:

      [LibraryName.]Component[.Version]

  This value is found in the registry and represents how the component's DLL is registered there. Although it sometimes contains the DLL name, it often does not. For example, the DLL from which you instantiate the Ad Rotator object is adrot.dll. However, its ProgID is MSWC.AdRotator.1, as defined by the default value of the following registry key:

      HKEY_CLASSES_ROOT\CLSID\{1621F7C0-60AC-11CF-9427-444553540000}\ProgID

  As you will note, this is the ProgID for the registered DLL and contains version information in addition to its registered name. Sometimes, however, you may have several different versions of the same DLL registered on your machine. In this case, you can use the default value of the VersionIndependentProgID registry key to instantiate the most recent version of the DLL. In our example (the ad rotator), the version-independent ProgID is MSWC.AdRotator.

Example
    <%

    ' The following code uses the CreateObject method of
    ' the Server object to instantiate an Ad Rotator object
    ' on the server.
    Dim objAdRotator

    Set objAdRotator = Server.CreateObject("MSWC.AdRotator")

    %>
Notes
When a client browser requests an ASP script containing objects, ASP instantiates the objects (thus triggering their default constructor functions, if they exist) and then immediately—before any script is processed—calls the OnStartPage method of every object on the page that has a defined OnStartPage event handler. The OnStartPage method allows the object to use the ObjectContext object to retrieve pointers to the built-in ASP objects. The details behind the ObjectContext object and the OnStartPage methods of server components is beyond the scope of this book. For more information on this, see Shelley Powers' book, Developing ASP Components, published by O'Reilly & Associates.

Using the CreateObject method creates a server-side object with page-level scope, unless CreateObject is called in the Application_ OnStart or Session_OnStart events, in which case the object will be instantiated with application- or session-level scope, respectively. Objects with page-level scope are destroyed and the memory they occupy is released at the end of the page.

To create an object with application scope, you must call the CreateObject method in the Application_OnStart event (see Chapter 4, for more details) or use the <OBJECT> tag in the GLOBAL.ASA file and set the SCOPE parameter to Application. (For more details on the GLOBAL.ASA file, see Chapter 11.)

Likewise, to create an object with session scope, you must call the CreateObject method in the Session_OnStart event (see Chapter 10, for more details) or use the <OBJECT> tag in the GLOBAL.ASA file and set the SCOPE parameter to Session. Also, you can use a Session variable to hold the object instantiated using CreateObject, as in the following example:

    Set Session("objMyAdRot") = _
        Server.CreateObject("MSWC.AdRotator")

Objects with application-level scope are not destroyed until the Application_OnEnd event is fired. Session-scoped objects are similarly destroyed at the end of a user's session or when the Abandon method of the Session object is called; see Chapter 10 for more details.

Once an object is instantiated, it can be destroyed by setting its value to the keyword Nothing, as in the following example code:

    Set objMyAdRot = Nothing

You also can simply replace the value of the object variable to release the memory being used for the original object:

    Set objMyAdRot = strSomeOtherValue

You cannot use CreateObject to create an instance of one of the built-in objects. For example the following code will generate a runtime error:

    Set objMySession = Server.CreateObject("Session") ' WRONG

Execute |
Server.Execute (strPath)
The Execute method allows you to call and execute an ASP script from within another ASP script. When the called script has finished executing, control returns to the ASP page that issued the Server.Execute method call. Using the Execute method, you can break complex applications down into modular, reusable components that can be called when needed. The Execute method is new to ASP 3.0/IIS 5.0.
Parameters

strPath

  The absolute or relative path to the ASP script you wish to execute. Only scripts within the current application's application space can be executed using this method.

Example
In this example, the second script, which displays a text advertisement, is called (using the Execute method) by the first script only if the current user has not entered the "No Ad" club.
    **** BEGIN ExecuteExamplePage.ASP ********
    <HTML>
    <HEAD>
    <TITLE>
    Execute Example Form
    </TITLE>
    </HEAD>
    <BODY>
    <%
    ' This script executes an advertisement if the current
    ' user is not a member of the "No advertisement" club.

    ' Dimension Local variables.
    Dim blnNoAdClub

    ' Test Session variable.
    Session("blnNoAdClub") = False

    ' Set variables.
    blnNoAdClub = Session("blnNoAdClub")

    ' If the user belongs in the "No Ad" club don't show an ad.
    If Not(blnNoAdClub) Then
    	Server.Execute ("DisplayAdvertisement.asp")
    End If
    %>

    FROM HERE DOWN IS ALL CONTENT FROM ExecuteExampleForm.asp<BR>

    This page may or may not have an advertisement line at the top.

    </BODY>
    </HTML>
    **** END ExecuteExamplePage.ASP ********

    **** BEGIN DisplayAdvertisement.ASP ********
    <%
    Dim intSal
    Dim strPos
    Dim strAdString

    ' Test Session variable.
    Session("intSal") = 4
    Session("strPos") = "vp"

    intSal = Session("intSal")
    strPos = Session("strPos")

    ' Initialize first part of ad banner text.
    strAdString = "Click here to request a credit card"

    ' Add credit limit phrase to ad.
    Select Case intSal
    	Case 0 ' From $10K to $20K in salary.
    		strAdString = strAdString & " with a limit of up to $5000"
    	Case 1 ' From $20K+ to $40K in salary.
    		strAdString = strAdString & " with a limit of up to $10000"
    	Case 2 ' From $40K+ to $60K in salary.
    		strAdString = strAdString & " with a limit of up to $20000"
    	Case 3 ' From $60K+ to $80K in salary.
    		strAdString = strAdString & " with a limit of up to $50000"
    	Case 4 ' From $80K+ in salary.
    		strAdString = strAdString & " with a limit of up to $100000"
    	Case Else ' Assume lowest salary range.
    		strAdString = strAdString & " with no limit"
    End Select

    ' Add exclusivity phrase if necessary.
    If UCase(strPos) = "VP" Then
    	strAdString = strAdString & " just for executives!"
    Else
    	strAdString = strAdString & "!"
    End If

    ' Display advertisement text string.
    Response.Write "<FONT SIZE="5" COLOR = "red">" & strAdString & "</FONT><BR><BR>"

    %>
    **** END DisplayAdvertisement.ASP ********
Notes
The Execute method provides ASP developers an excellent opportunity to break up their applications into manageable, reusable components of code that can be called only when necessary. In the past, an ASP developer was forced to either programmatically redirect the execution of a page to another page (a costly exercise in execution speed, since it required that a header be sent to the browser to redirect the browser's request) or include another file using the #INCLUDE pre-processor directive. Neither alternative was very useful. As previously mentioned, the Redirect method of the Server object (see later in this chapter) calls for another server-to-client-server round of calls for a page that was slow. The #INCLUDE directive forces the ASP ISAPI filter to retrieve the included file from the file system, insert it into the current script, and interpret all the included code even if it is never used by the including script.

The Execute method, on the other hand, allows you to execute other scripts programmatically only when the logic in the calling script requires it. That is, the Execute method allows you to dynamically include scripts.

Note that just as with other scripts, scripts called through the Execute method can add or modify HTTP headers included in the response. However, just as with standalone scripts, if the called script adds or modifies any HTTP headers after any response is sent, an error will be generated.

As you might expect, the variable scope for each script (calling script and called script) is distinct. For example, in the following code, you have a variable called strName in both scripts.

    CALLING SCRIPT
    <%
    Dim strName
    strName = "Sam"
    Server.Execute("CalledScript.asp")
    %>

    CalledScript.asp
    <%
    Dim strName
    Response.Write strName
    %>

In the preceding example, strName is declared in both scripts. However, it is not initialized in the second script. In this example, Response.Write would result in nothing being written to the Response, as the value of strName in the called script is undefined.

When an ASP page calls Server.Execute to branch to another ASP page, all of the former's built-in ASP objects are passed to the called script. For example, any values in the Request object's Form collection are available to the ASP page invoked by the call to the Server object's Execute method.

Note that according to the Microsoft documentation, the Execute method will allow you to add a QueryString parameter to the end of the called URL. However, as of the writing of this addition of this book (March 2000), adding a QueryString to a URL will generate an error. According to Microsoft Technical Support, this is a known bug in IIS 5.0 and a fix is in development.

Finally, if you call a script using the Execute method from within a script that you have set to transactional and the called script causes the transaction to be aborted, the OnTransactionAbort event on the called page will be called first and then, after the called script has completed execution, the OnTransactionAbort event on the calling page is executed. For example, suppose the following script, CallingScript.ASP, calls the CalledScript.ASP script further.

    CALLINGSCRIPT.ASP
    <%@ TRANSACTION=Required%>
    <%
    Server.Execute "CalledScript.asp?strName=bob"
    Sub OnTransactionAbort( )
    	'Clean up code for CallingScript.asp.
    End Sub

    Sub OnTransactionCommit( )
    	Commit code for CalledScript.asp.
    End Sub

    CALLEDSCRIPT.ASP
    <%@ TRANSACTION=Required%>
    <%
    .
    .
    .
    'Processing code....
    .
    .
    .
    OnTransactionAbort( )
    	'Clean up code for CalledScript.asp.
    End Sub

    OnTransactionCommit( )
    	Commit code for CalledScript.asp.
    End Sub

If in CalledScript.ASP script, an error occurs that forces the transaction to abort, then the OnTransactionAbort event code for CalledScript.ASP would be executed and then the OnTransactionAbort event code for CallingScript.ASP would be executed.

GetLastError |
Set objASPErr = Server.GetLastError ()
The GetLastError method of the Server object allows you to display information about any error that occurs in your script. The GetLastError method returns a single ASPError object (see Chapter 5. You can use the returned ASPError object to display or programmatically respond to error information. The GetLastError method is new to ASP 3.0/IIS 5.0
Parameters

objASPErr

  The name of the ASPError object returned by the GetLastError method.

Example
    <%
    ' Instantiate an ASPError object using the GetLastError method of the
    ' Server object.
    Set objASPError = Server.GetLastError
    %>
    .
    .
    .
    HTML Display Etc.
    <%
    ' Use the properties of the ASPError object (returned by the GetLastError
    ' object) to display information about the error.

    ' *** FOR MORE INFORMATION, SEE THE ASPERROR OBJECT CHAPTER.

    Response.Write Server.HTMLEncode(objASPError.Category)
    If objASPError.ASPCode > " Then
        Response.Write Server.HTMLEncode(", " & objASPError.ASPCode)
    End If
    Response.Write Server.HTMLEncode(" (0x" & Hex(objASPError.Number) & ")" )
    & "<br>"
    If objASPError.ASPDescription > " Then
       Response.Write Server.HTMLEncode(objASPError.ASPDescription) & "<br>"
    ElseIf (objASPError.Description > ") Then
       Response.Write Server.HTMLEncode(objASPError.Description) & "<br>" End if
      .
      .
      .
Notes
In this code example (derived from the default 500-100.ASP script that comes with IIS 5.0), the script begins by instantiating an ASPError object using the GetLast-Error method. It then displays information about the last error by using the properties of the ASPError object. For more information on the properties of the ASPError object, see Chapter 5.

It is important to note that you cannot use the GetLastError method in the script in which the error occurs. For example, the following code will not work as you might expect it to:

    <%
    On Error Resume Next
    Session("MyVar"3333) = "keyton"
    Set objError = Server.GetLastError( )
    Response.Write objError.ASPCode
    %>

You might expect that, because you had used the On Error Resume Next statement, you could then react to errors later in the script by using the GetLastError method. Unfortunately, this is not the case. IIS 5.0 responds instantly to errors and redirects the client using the Server.Transfer method ("behind the scenes") to an error-handling page. By default, this error page is /iisHelp/Common/500-100.ASP. It is in this page that you can customize error handling using the GetLastError method.

For more information on the 500-100.ASP error-handling page and on error-handling in your scripts in general, see Chapter 5.

The GetLastError method works for preprocessing errors, script compilation errors, and run-time errors.

It is important to note that the GetLastError method will only return error information successfully if no content has been sent to the client. If content has already been sent to the client, the GetLastError method itself causes an error. For this reason, if you have scripts within which you feel that you will need to handle various errors, it is a good idea to set the Buffer property of the Response object to True (See Chapter 8):

    Response.Buffer = True

For more information on the GetLastError method and the ASPError object it returns, see Chapter 5.

HTMLEncode |
Server.HTMLEncode (strHTMLString)
If you ever need to display the actual HTML code involved in an HTML page or ASP script, you must use the HTMLEncode method of the Server object. The HTMLEncode method of the Server object allows you to encode the HTML string so that, when it is displayed in the browser, the browser does not simply interpret the HTML as instructions for text layout.
Parameters

strHTMLString

  The string whose HTML code you wish to encode for display on the client machine.

Example
    <%

    ' The following code encodes these HTML tags so that they can
    ' be displayed without interpretation on the client browser:
    ' <TABLE><TR><TD></TD></TR></TABLE>
    Dim strOldHTML
    Dim strNeutralCode

    strOldHTML = "<TABLE><TR><TD>"
    strNeutralCode = Server.HTMLEncode(strOldHTML)

    ' The variable strNeutralCode now holds the following code:
    ' &lt;TABLE&gt;&lt;TR&gt;&lt;TD&gt;
    ' but will be displayed on the client's machine as
    ' <TABLE><TR><TD>
    ' and the &lt;TABLE&gt;&lt;TR&gt;&lt;TD&gt; will be
    ' seen only if you view the source code on the client.
    Response.Write strNeutralCode

    %>
Notes
The HTMLEncode method is a straightforward method that is simple to use. It makes it possible to display the source code of your HTML page or to demonstrate the use of various HTML tags in a web page. It is also invaluable for displaying the output of database queries.

MapPath |
Server.MapPath (strPath)
The MapPath method allows you to determine the physical path on the server, given a virtual or relative path.
Parameters

strPath

  A complete virtual path or a path relative to the path of the current script's home directory on the server. The method determines how to interpret the string depending on if it starts with either a slash (/) or a backslash (\). If the strPath parameter begins with either of these characters, the string is assumed to be a complete virtual path. Otherwise, the physical path returned is the path relative to the current script's physical directory on the web server.

Example
    <%

    ' The following line of code determines the physical path
    ' of the current script for later use.
    strSearchPath = _
       Server.MapPath("/searchscripts/start/searchstart.asp")

    ' This following code then uses the strSearchPath string to
    ' determine the file attributes for the current file for
    ' display in the client-side HTML.
    Set fs = Server.CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFile(strSearchPath)
    datFileLastModified = f.DateLastModified
    %>
    <HTML>
    <HEAD><TITLE>MapPath Example</TITLE></HEAD>
    <BODY>
    The current script was last modified <%=datFileLastModified%>.
    </BODY>
    </HTML>
Notes
There are two important facts to remember when using the MapPath method. The first is that it does not support the standard MS-DOS relative directory notation ("." and ".."). For this reason, the following line of code will result in a runtime error:
    strSearchPath = Server.MapPath("../start/searchstart.asp")
Second, the MapPath method does not check to ensure whether a given physical directory exists. For this reason, this method is useful in determining the physical path for a new file to be created by the web server in response to a line of script code.

Finally, to determine the physical path of the current file, you can use the PATH_INFO element of the Request object's ServerVariables collection (for more details, see Chapter 7). For example, assume the current script is searchstart.ASP and it is located in the /searchscripts/start/ virtual directory. The following line of code would set the value of strSearchPath to D:\apps\searchscripts\start\searchstart.ASP :

    strSearchPath = _
       Server.MapPath(Request.ServerVariables("PATH_INFO"))

Transfer |
Server.Transfer (strPath)
The Transfer method allows the developer to redirect execution from one script to another script without an HTTP response being sent to the client. All information from the first script, including values in the Request and other objects, is available in full to the second script. Unlike Server.Execute, Server.Transfer does not return control to the script that called the Transfer method when the called ASP page has Finished executing. The method is new to ASP 3.0/IIS 5.0.
Parameters

strPath

  The relative or absolute path to the second script to which execution will be redirected.

Example
    ******** BEGIN Transfer Example: First Script ********

    <%
    ' Transfer Example: First Script

    ' First Script calls Second Script, which uses Transfer
    ' to redirect execution to Third Script.
    %>
    <HTML>
    <HEAD>
    <TITLE>
    Server.Transfer Example
    </TITLE>
    </HEAD>
    <BODY>
    <FORM ACTION="TransferExample_Process1.asp?qsvalue=hannah1" METHOD="post">
    First Name: <INPUT TYPE="text" NAME="txtFName" VALUE="><BR>
    Last Name: <INPUT TYPE="text" NAME="txtLName" VALUE="><BR>
    Address: <INPUT TYPE="text" NAME="txtAddress" VALUE="><BR>
    City: <INPUT TYPE="text" NAME="txtCity" VALUE=">&nbsp
    State: <INPUT TYPE="text" NAME="txtState" VALUE="><BR>
    Zipcode: <INPUT TYPE="text" NAME="txtZipcode" VALUE="><BR>
    <INPUT TYPE="submit" VALUE="Submit">
    </FORM>
    </BODY>
    </HTML>
    ******** END Transfer Example: First Script ********

    ******** BEGIN Transfer Example: Second Script ********
    <%
    Application("strExample1") = "ApplicationStringValue"
    Session("strExample2") = "SessionStringValue"
    Server.Transfer "TransferExample_Process2.asp"
    Application("strExample1") = "NEWApplicationStringValue"
    Session("strExample2") = "NEWSessionStringValue"
    %>
    ******** END Transfer Example: Second Script ********

    ******** Begin Transfer Example: Third Script ********
    <%
    ' Transfer Example: Third Page

    ' First Page calls Second Page, which uses Transfer
    ' to redirect execution to Third Page.
    %>
    <HTML>
    <HEAD>
    <TITLE>
    Server.Transfer Example
    </TITLE>
    </HEAD>
    <BODY>
    <%
    Response.Write "First Name: " & Request.Form("txtFName") & "<BR>"
    Response.Write "Last Name: " & Request.Form("txtLName") & "<BR>"
    Response.Write "Address: " & Request.Form("txtAddress") & "<BR>"
    Response.Write "City: " & Request.Form("txtCity") & "<BR>"
    Response.Write "State: " & Request.Form("txtState") & "<BR>"
    Response.Write "Zipcode: " & Request.Form("txtZipcode") & "<BR><BR>"

    Response.Write "Application Variable: " & Application("strExample1") & "<BR>"
    Response.Write "Session Variable: " & Session("strExample2") & "<BR>"

    %>

    </BODY>
    </HTML>
    ******** END Transfer Example: Third Script ********
Notes
If you use this code, create the three scripts, and test them in a browser, you will see something similar to the following as a final result:
    First Name: keyton
    Last Name: weissinger
    Address: 123 Main Street
    City: Somewhereville
    State: Alabama
    Zipcode: 30087

    Application Variable: ApplicationStringValue
    Session Variable: SessionStringValue
Note that the Application and Session variables are not updated by the code in the block after the call to the Transfer method. As demonstrated in the example, when you call the Transfer method, all information available to the first script from the built-in ASP objects is also available to the second script. Note, however, that this is not the case for script-level variables. If you declare and initialize a variable in the first script, it is not available in the second script.

Also, if there are any variables with Application- or Session-level scope, the second script also has access to these—even if the second script is in another application space.

It is important to note two things about the Transfer method. The first is that, as you might expect, an error will be raised if you attempt to use the Transfer method after some response has already been sent to the client, so set the Buffer property of the Response object to True to avoid this problem, if appropriate.

The second thing to note about the Transfer method is that no further script after the call to Transfer method is executed. For example, in the following example, the third and fourth lines of code will be completely ignored:

    Session("intMyVar") = 1
    Server.Transfer "SomeOtherScript.asp"
    Session("intMyVar") = 2
    Session("intMyOtherVar") = 3

After the execution of the preceding block of code, the Session variable, intMyVar will still have the value of 1 and the intMyOtherVar variable will still be undefined unless defined elsewhere before the execution of this block of code.

URLEncode |
Server.URLEncode (strURL)
Encodes a string that can then be sent over the address line as a query string.
Parameters

strURL

  The string value you want to encode to send over the address line as a query string.

Example
    <%

    ' The following encodes the URL
    ' http://www.myserver.com/apps/search.asp
    Dim strOldURL
    Dim strNewURL

    strOldURL = "http://www.myserver.com/apps/search.asp"
    strNewURL = Server.URLEncode(strOldURL)

    ' This encoding results in the following string value being
    ' placed in the strNewURL variable:
    ' http%3A%2F%2Fwww%2Emyserver%2Ecom%2Fapps%2Fsearch%2Easp

    ' This new string value could be used in a query string to
    ' represent a "next script," as demonstrated here:

    %>
    <HTML>
    <HEAD><TITLE>URLEncode Example</TITLE></HEAD>
    <BODY>
    <FORM ACTION="/apps/CalcAndRedirect.asp?newURL=<%=strNewURL%>" METHOD = POST>
    <INPUT TYPE = TEXT NAME = "First Value">
    <INPUT TYPE = TEXT NAME = "Second Value">
    <INPUT TYPE = SUBMIT NAME = "Calculate Results">
    </FORM>
    </BODY>
    </HTML>
Notes
The URLEncode method, like the HTMLEncode method, is straightforward and easy to use. It is imperative that you use the URLEncode method any time you are forced to send information over the address line instead of posting information using the POST method. If you do not encode your information and place it into the QueryString collection (through the GET method), its interpretation is unpredictable, depending on the data sent.

If you send information in the query string (i.e., from visible frame to visible frame), but not over the address line, this encoding is done for you.