Storing data on the client in hidden fields or URL parameters is
the simplest technique. To do this, you must dynamically generate
all of the HTML pages in your application except for the initial page.
Because each page functions as a mechanism for transporting data values
from the previous stored process to the next stored process, it cannot
be static HTML stored in a file.
Usually, the application
takes the following steps:
-
The first HTML page
is a welcome or login screen for the application. After the user enters
any required information, the first stored process is executed by
submitting a form or clicking on a link.
-
The first stored process
performs any necessary validation on the submitted parameters and
any required application initialization.
-
The first stored process
writes an HTML page to the _WEBOUT output stream. This HTML page might
be an initial report or it might be the next navigation page in the
application. Links in this page typically execute another stored process
and pass user identity, user preferences, application state, or any
other useful information through hidden form fields or URL parameters.
-
Each succeeding link
in the application executes another stored process and passes any
required information through the same technique.
Each hidden field in
the second form can contain one name/value pair that is passed from
the first form. You should use unique names for all of the data values
in the entire application. In this way, you can pass all of the
application data throughout the entire application.
When you dynamically
generate the second form, you can write out the name of the second
stored process in the hidden field _PROGRAM. Because the first stored
process contains the logic to determine the second stored process,
this is referred to as chaining stored processes. A stored process
can chain to multiple stored processes depending on the link that
a user chooses or on data that is entered by the users. The stored
process can even chain back to itself.
In the following example,
the
MyWebApp
application starts with a static
HTML welcome page:
<!-- Welcome page for MyWebApp -->
<HTML>
<HEAD><TITLE>Welcome to MyWebApp
</TITLE></HEAD>
<BODY><H1>Welcome to MyWebApp</H1>
<FORM ACTION="/SASStoredProcess/do">
Please enter your first name:
<INPUT TYPE="text" NAME="FNAME"><BR>
<INPUT TYPE="hidden" NAME="_program"
VALUE="/WebApps/MyWebApp/Ask Color">
<INPUT TYPE="submit" VALUE="Run Program">
</FORM>
</BODY></HTML>
This welcome page prompts
the user for a first name and passes the value as the FNAME input
parameter to the
/WebApps/MyWebApp/Ask Color
stored process, as in the following example:
/* Ask Color stored process
*
* This stored process prompts for the user's favorite
* and passes it to the Print Color stored process.
*/
data _null_;
file _webout;
put '<HTML>';
put '<H1>Welcome to MyWebApp</H1>';
/* Create reference back to the Stored Process
Web Application from special automatic
macro variable _URL. */
put "<FORM ACTION='&_URL'>";
/* Specify the stored process to be executed using
the _PROGRAM variable. */
put '<INPUT TYPE="hidden" NAME="_program" '
'VALUE="/WebApps/MyWebApp/Print Color">';
/* Pass first name value on to next program.
The value is user entered text, so you must
encode it for use in HTML. */
fname = htmlencode("&FNAME", 'amp lt gt quot');
put '<INPUT TYPE="hidden" NAME="fname" VALUE="'
fname +(-1) '"><BR>';
put 'What is your favorite color?';
put '<SELECT SIZE=1 NAME="fcolor">';
put '<OPTION VALUE="red">red</OPTION>';
put '<OPTION VALUE="green">green</OPTION>';
put '<OPTION VALUE="blue">blue</OPTION>';
put '<OPTION VALUE="other">other</OPTION>';
put '</SELECT><BR>';
put '<INPUT TYPE="submit" VALUE="Run Program">';
put '</FORM>';
put '</HTML>';
run;
This stored process
simply creates an HTML form that prompts the user for more information.
The reserved macro variable _URL is used to refer back to the SAS
Stored Process Web Application. This enables you to move the Web application
without modifying each stored process. The _PROGRAM variable specifies
the stored process that processes the contents of the form when it
is submitted. In order to keep the FNAME that was entered in the initial
page, place it in the form as a hidden field. Because the value was
entered by the user, it must be encoded using the HTMLENCODE function
in case it contains any character that might be interpreted as HTML
syntax. The form prompts the user for a color choice and chains to
a new stored process named
Print Color
, as
in the following example:
/* Print Color stored process
*
* This stored process prints the user's
* first name and favorite color.
*/
data _null_;
file _webout;
put '<HTML>';
fname = htmlencode("&FNAME");
put 'Your first name is <b>'
fname +(-1) '</b>';
put '<BR>';
put "Your favorite color is
<b>&FCOLOR</b>";
put '<BR>';
put '</HTML>';
run;
The
Print
Color
stored process prints the values of the variables
from both the first and second forms, illustrating that the data has
been correctly passed throughout the entire application.
A variation of this
technique uses URL parameters instead of hidden form fields. The following
example code is an alternative implementation of the
Ask
Color
stored process:
/* Ask Color stored process
*
* This stored process prompts for the user's favorite
* and passes it to the Print Color stored process.
*/
data _null_;
file _webout;
put '<HTML>';
put '<H1>Welcome to MyWebApp</H1>';
/* Build a URL referencing the next stored process.
* Use URLENCODE to encode any special characters in
* any parameters. */
length nexturl $500;
nexturl = "&_URL?_program=
/WebApps/MyWebApp/Print Color" ||
'&fname=' || urlencode("&FNAME");
put 'What is your favorite color?';
put '<UL>';
put '<LI><A HREF="' nexturl +(-1)
'&color=red">red</A></LI>';
put '<LI><A HREF="' nexturl +(-1)
'&color=green">green</A></LI>';
put '<LI><A HREF="' nexturl +(-1)
'&color=blue">blue</A></LI>';
put '<LI><A HREF="' nexturl +(-1)
'&color=other">other</A></LI>';
put '</UL>';
put '</HTML>';
run;
This stored process
generates a separate URL link for each color choice. The end result
is the same as the first implementation of
Ask Color
; the
Print Color
stored process is executed
with both FNAME and COLOR input parameters.
The technique of passing
data by using hidden fields or URL parameters has the following advantages:
-
-
-
state is maintained indefinitely
-
allows stored processes to be distributed
across multiple servers
The major disadvantages
of this technique are the necessity to use dynamically generated HTML
for all pages in the application and the security and visibility of
the data. The data in hidden fields is readily visible to the client
by viewing the HTML source (and is directly visible in the URL when
using GET method forms). The data is easily changed by the user, and
falsified or inconsistent data can be submitted to the application.
Sensitive data should be validated in each new stored process, even
if it is passed from generated hidden fields.