Once in a while, on applications under heavy load, we’ve faced situations where some grids suddenly lost their columns, meaning that their (.RecordSource) was unexpectedly USE IN.

After double checking the FoxInCloud code, seeing no correlation with the type of .recordSource (table, view or cursor), we progressively circumscribed the problem within an area of code where the contents of the grid is turned into XML for state comparison.

And finally we found what was going on…

VFP CursorToXML() bug

Yes, you read it right, the VFP CursorToXML() function has a bug!

Under certain conditions that honestly we could not isolate, maybe once out of 20,000 calls, without any obvious relation with the data contained in the cursor, CursorToXML() sometimes returns this XML:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?><VFPData</VFPData>

Looks like an error in the pointer when writing the closing tag </VFPData> resulting in a malformed XML, and containing no data at all!

If you wish to investigate this bug, you can download here sample data that CursorToXML() has failed to properly convert while in production, all resulting in the XML shown above.

And if you attempt to convert these sample data with CursorToXML() on your dev. machine, it’ll most probably succeed…
That can probably be called an ‘intermittent bug’!

Workaround

FoxInCloud processes all CursorToXML() through a central function: cXMLofCursor().

Whenever it finds mismatched < or > in the result from CursorToXML(), cXMLofCursor() simply builds the XML string by scanning the cursor’s rows and columns. This obviously takes a little overhead however it happens only once in thousands calls and is 100% successful.

Result: four-nine availability

After solving this VFP bug, applications in production now meet the highest standards for availability, over 99.99%:

Biosil Web Application

Biolabo Web Application

Special thanks

We could not have successfully achieved such a difficult debug without the close cooperation and help of our friends of the FoxInCloud users community!

Many thanks to the FoxInCloud users1 who accepted to share logs, put experimental code into production, with sometimes failures and moments of discouragement… We finally did it: turned down a VFP bug that has spoiled us for quite a while…!

Wait, version 2.27 brings more than just a bug fix!

Out of the 15+ enhancements and fixes brought by version 2.27.0, let’s focus on 2 that’ll probably suit many VFP developers needs…

Paged grid: faster and updatable

In a Web Application, because of the limited bandwidth, browsing through long lists remains a response time issue.

As VFP application extensively use grids to present long lists of data, FoxInCloud comes with a handy class that turns any VFP grid into a paged grid 2 where the whole set of rows is divided into pages of 20-100 rows. The user can:

  • choose the number of lines per page
  • by clicking the header of any column where .RecordSource an index: sort by left-click, filter by right-click
  • move to given page by typing its number
  • navigate between page by clicking arrows
  • seamlessly move to the previous or next page just by browsing past the first or last line in the page

Grid paging container

The paged grid in action on FoxInCloud Live Tutorial:

FoxInCloud Live Tutorial - paged grid

Until this version 2.27.0, the data displayed in the grid were those of a cursor built from the grid.recordSource, and replacing the corresponding columns.controlSource. Because of that design, building a page with a large [col * row] count could take some time and the grid could hardly be updateable.

Starting with V 2.27.0, awCntGrdPage:

  • builds the page cursor with only the unique keys of the records that appear on the page, in the suitable order,
  • sets this one-key column cursor as the grid.recordSource,
  • sets a relation from the page cursor to the original grid.recordSource on the key columns 3,
  • keeps the columns.controlSource unchanged, pointing on the original grid.recordSource Alias, and/or related Aliases.

awCntGrdPage.wlCntGrcCSpageCursor lets you switch between the legacy and the new behavior:

  • .T. (current default) – legacy behavior: redirect columns.controlSource to the page cursor
  • .F. (future default) – new behavior: keep columns.controlSource and set a relation from the page cursor into the original grid.recordSource

Surface Events Live Tutorial

Surface Events –or Client-side Events– are events that trigger fast and alter only the aspect of the display and/or static contents, and thus don’t require an interaction with the data on the server: .MouseEnter(), .MouseMove(), .MouseLeave(), .KeyPress(), .InteractiveChange()

In short Surface Events only affect the surface of the application without requesting the server.

As they must entirely be processed on the client browser, Surface Events are the only area of a FoxInCloud application where the VFP developer must write some JavaScript and/or CSS code.

FoxInCloud Live Tutorial now provides an on-line sample form where all possible alternative techniques for writing such code are discussed:

FoxInCloud Live Tutorial's *Surface Event* form

The corresponding blog post and video provide additional detailed explanation.


  1. Special thanks to Gilles Lajot-Sarthou (among others) 

  2. modify class awCntGrdPage of aw.vcx; this class requires that grid.recordSource has at least a unique key (primary or candidate

  3. whenever grid.recordSource is already the target of a relation, behavior automatically switches back to legacy and grid is set to read-only 



Watch FoxInCloud Marketing Videos :: Watch FoxInCloud Technical Videos :: Stay tuned on FoxInCloud Roadmap :: Learn how to use FoxInCloud :: Download FoxInCloud Adaptation Assistant for free :: Download FoxInCloud Web Application Studio for free