Web Connect How To : Show Me the Code!

 LAFOX Home How URL Maps to Code  LAFOX Design Oveview  Framework Extensions 
Show Me the Design!

Design Overview

design has several key goals:

  • Organize code into simple logical pieces.
  • Eliminate PRIVATE variables in our pages.
  • Improve Error Handling
  • Make Server Side Session Variables easy to use.
  • Browse large query results.
  • Allow Multiple web sites to run using the same code.

Organize Code into Simple Logical Pieces

Our previous Web-Connect projects have turned out well,  but our code organization was not ideal.

The first projects that we did had huge prg files - a real kitchen sink approach - with all the code typically in one or two prg files.
Our next projects split each web hit into; data, presentation, and business prg files.  This led to a huge number of prg files.

For this project, I used the page as our organizing principle. 
The code for each page is in its own prg and is based on the rbPage class.
Each page has only a few methods, and all the supporting functions are grouped together with the code that is using them.
A typical rbPage class will have:

  • Page()        : Show the page to the user.
  • Submit()    : User submits page to web server.
  • OtherFunctions()    : Supporting functions - used by Page() or Submit()

Goldilocks would find this approach "just right":

  • Not too many functions
  • Not too many prg files.

Eliminate PRIVATE Variables in Our Pages

Web Connect projects usually send the page back to the user with Response.ExpandTemplate().
ExpandTemplate() merges together FoxPro variables with an HTML template.

The HTML template refers to FoxPro variables by embedding the variable with delimiters like this:

ExpandTemplate() does the following:

  • Parses the HTML template
  • Finds all delimited variables
  • Evaluates the variables
  • Plugs the evaluation result back into the HTML template
  • Sends the result to the user.

ExpandTemplate() does not and cannot "know" how many FoxPro variables you want to insert into an HTML page,
so sending them in as parameters to ExpandTemplate() can't work.  The typical way to code around this is to declare
your FoxPro variables as PRIVATE so they will "drop" into ExpandTemplate().

A few PRIVATE variables might be ok when used sparingly. 
However, we strongly discourage PRIVATE variables everywhere else in our code,
so why allow them here?

Code with PRIVATE variables would fail code review in our company and be sent back for a re-write.
Variables parachuting in from parts unknown just make for messy code that could blow up when you try to change it.

Instead of PRIVATE variables, we just add properties to our page class like this:

   ** Merge Variables For HTML Page
   ** rbPage Properties can be merged into our HTML template

   UserGroupHeader   = []
   UserGroupFooter   = []

Since One Class = One Page, we can refer to THIS in our HTML template like this:

Improve Error Handling

Web Connect does a pretty good job with error handling. 
There are a couple of things that I would like to see done better.

1.  Stop the avalanche of error messages caused by errors in your code.
If your code gets an error, it sometimes generates an avalanche of error messages.

The first error hits, gives an error message... and then VFP tries to execute the next line of code.
Why?  Oh my gosh, WHY?

After the first error, the remaining lines of code will almost certainly fail.
Worse than that, since it is executing each line of code, it can take a long time, and tie up your server resources.
Code that should run in .05 seconds can take 10 to 15 seconds -  an eternity in web server time.

So, when we get an error we should just report the first error, and go home.

2.  Don't use old fashioned ON ERROR error trapping for merge errors in your HTML.
As we evaluate each merge variable in our HTML template, we have to deal with evaluation errors.
A variable could be misspelled, out of scope, etc., so we must deal with it.

Microsoft has improved TextMerge in VFP 7, but any error during the merge still kills the whole page.
Not a good result.
It is better to evaluate as many merge variables in the template as possible, so that minor errors don't stop your site.

Web Connect's ExpandTemplate() handles merge errors by setting an ON ERROR handler  before the merge, and then resetting it after the merge.
It works well, but under some circumstances, the ON ERROR is not re-set.  Uh Oh!

How to fix both problems:
Write our own version of ExpandTemplate() that:
1.  Uses FoxPro's RETURN TO so that we bail out after the first error.
2.  Uses the Error() method of a class to trap errors.  This eliminates the need to use a global ON ERROR trap.
See rbPage::Merge() and rbPage::MergeToString()

Make Server Side Session Variables easy to use
Web programming is a little strange.
Each web hit is independent.
You don't know what pages the user has been to, what they have done, or even if the user is ever going to come back.

    For each hit the browser:
  • Connects
  • Sends it's request to the web server
  • Gets your response
  • Disconnects

Web programming is often called "Stateless." 
Remember, your code is executing on the web server, not on the user's machine.
Worse than that, all user code is executing in the same space on the server.
Same data session.
Same tables open.
Same variables in scope.
A variable in scope for one user is in scope for all users.

Cookies are a partial answer.
Cookies are a set of up to 20 variables that you can store on the user's machine from the web server.