This morning I was asked the question 'what can I use to replace the windows popup "Yes/No" confirmation?' by a developer getting to grips with WebApp programming (we've all been there and it isn't the easiest), so as well as answering the question, I wrote a small web view to illustrate the mechanism. After doing that I enhanced it a bit and so present it here for anybody who might find it useful (either for learning or for instruction).
It shows what process in the pool is being called at what points and shows a global variable and a regular property differing across them. For best results, set your Minimum pool to >= ~5 in WebApp Administrator.
If you run it under the debugger it will tell you nothing useful - you need open it outside the debugger, which in itself illustrates the need to test WebApps outside the debugger.
- The "Call Server" button just causes a simple round trip to the server.
- The "Yes/No" button initiates a cascade of YesNo and InfoBox pop-ups.
- The "Popup Dialog" button does what it says on the tin.
It combines both a view and a modal dialog in a single .wo file for simplicity. You should be able to use it in any web app, compile, then open the WebApp in the browser to see it work.
Code:
Use cWebView.pkg
Use cWebModalDialog.pkg
Use cWebPanel.pkg
Use cWebForm.pkg
Use cWebButton.pkg
Use cWebSpacer.pkg
#IFNDEF get_GetCurrentProcessId
External_Function GetCurrentProcessId "GetCurrentProcessId" Kernel32.Dll Returns Integer
#ENDIF
#IFNDEF _struct_stAllMyState
// Struct to hold state
Struct stAllMyState
Time tmClicked
String sFirstAswer
Time tmAnswered1
String SecondAnswer
Time tmAnswered2
Integer iProc1
Integer iProc2
Integer iProc3
End_Struct
#ENDIF
#IFNDEF C_CRLF
// Just for formatting the result of the Yes/No cascade in this case:
Define C_CRLF for (Character(13) + Character(10))
#ENDIF
// The following two items will (almost always) have different values
// in different processes in the WebApp process pool.
Global_Variable Integer giRandom
Move (Random(10000)) to giRandom
// Will be a property of oWabApp:
Property Integer piRandom (Random(10000) + 10000)
// This is a Modal Dialog which will be called from the View,
// included directly in-line here for simplicity:
Object oTestDialog is a cWebModalDialog
Set psCaption to "Test Dialog"
Set piMinWidth to 300
Set piMinHeight to 200
Set pbServerOnEscape to False // The only way out
Set pbShowClose to False // is to click "OK"
Set pbServerOnSubmit to True // enable the OnSubmit event
Object oMainPanel is a cWebPanel
Set piColumnCount to 12
Object oProcess is a cWebForm
Set piColumnSpan to 0
Set peLabelAlign to alignRight
Set pbReadOnly to True
Set psLabel to "This Process ID:"
Set piLabelOffset to 210
End_Object
Object oCaller is a cWebForm
Set piColumnSpan to 0
Set peLabelAlign to alignRight
Set pbReadOnly to True
Set psLabel to "Called from Process ID:"
Set piLabelOffset to 210
End_Object
Object oGlobal is a cWebForm
Set piColumnSpan to 0
Set peLabelAlign to alignRight
Set pbReadOnly to True
Set psLabel to "Global variable giRandom was:"
Set piLabelOffset to 210
End_Object
Object oRegProp is a cWebForm
Set piColumnSpan to 0
Set peLabelAlign to alignRight
Set pbReadOnly to True
Set psLabel to "Regular property piRandom was:"
Set piLabelOffset to 210
End_Object
End_Object
Object oBottomPanel is a cWebPanel
Set piColumnCount to 4
Set peRegion to prBottom
Object oOkButton is a cWebButton
Set psCaption to C_$OK
Set piColumnSpan to 1
Set piColumnIndex to 3
Procedure OnClick
Send Ok
End_Procedure
End_Object
End_Object
Procedure OnSubmit
Send Ok
End_Procedure
Procedure PopupTheDialog Handle hReturnObj Integer iCaller
Send Popup hReturnObj
WebSet psValue of oProcess to (GetCurrentProcessId())
WebSet psValue of oCaller to iCaller
WebSet psValue of oGlobal to giRandom
WebSet psValue of oRegProp to (piRandom(Self))
End_Procedure
Function DialogResult Returns String
String sResult
WebGet psValue of oProcess to sResult
Function_Return sResult
End_Function
End_Object
// This is the actual view
Object oProcPoolDemo is a cWebView
Set piWidth to 500
Set psCaption to "Process Pooling Effects Demo"
Set pbServerOnShow to True
Procedure OnShow
Send UpdateProcInfo
End_Procedure
Procedure UpdateProcInfo
WebSet psValue of oCurrProcess to (GetCurrentProcessId())
WebSet psValue of oGlobalVal to giRandom
WebSet psValue of oRegProp to (piRandom(Self))
End_Procedure
// Display this view at start up:
Delegate Set phoDefaultView to Self
Object oWebMainPanel is a cWebPanel
Set piColumnCount to 7
Object oCurrProcess is a cWebForm
Set piColumnIndex to 0
Set piColumnSpan to 5
Set pbReadOnly to True
Set psLabel to "Last invoked server process was:"
Set peLabelAlign to alignRight
Set piLabelOffset to 250
End_Object
Object oGlobalVal is a cWebForm
Set piColumnIndex to 0
Set piColumnSpan to 5
Set pbReadOnly to True
Set psLabel to "Global variable giRandom in that was:"
Set peLabelAlign to alignRight
Set piLabelOffset to 250
End_Object
Object oRegProp is a cWebForm
Set piColumnIndex to 0
Set piColumnSpan to 5
Set pbReadOnly to True
Set psLabel to "Regular property piRandom in that was:"
Set peLabelAlign to alignRight
Set piLabelOffset to 250
End_Object
Object oButtonSpacer is a cWebSpacer
Set piHeight to 20
End_Object
Object oCallServer is a cWebButton
Set piColumnIndex to 0
Set piColumnSpan to 2
Set psCaption to "Call Server"
Procedure OnClick
Send UpdateProcInfo
End_Procedure
End_Object
Object oYesNo is a cWebButton
Set piColumnIndex to 2
Set piColumnSpan to 2
Set psCaption to "Yes/No"
// Web Property to hold state between browser/server round-trips
{ WebProperty=Client }
Property stAllMyState ptState
// Is called in response to user's second answer:
Procedure ProcessSecondAnswer Integer eAnswer
stAllMyState tState
String[] asInfo
Send UpdateProcInfo
WebGet ptState to tState
Move (GetCurrentProcessId()) to tState.iProc3
Move (CurrentDateTime()) to tState.tmAnswered2
Move (If((eAnswer = cmYes), "Yes", "No")) to tState.SecondAnswer
// Assemble results:
Move ("You clicked the 'Yes/No' button at" * String(tState.tmClicked) * ;
"in process" * String(tState.iProc1)) ;
to asInfo[SizeOfArray(asInfo)]
Move ("Your first answer was: '" + ;
tState.sFirstAswer + "' at" * String(tState.tmAnswered1) * ;
"in process" * String(tState.iProc2)) ;
to asInfo[SizeOfArray(asInfo)]
Move ("Your second answer was: '" + ;
tState.SecondAnswer + "' at" * String(tState.tmAnswered2) * ;
"in process" * String(tState.iProc3)) ;
to asInfo[SizeOfArray(asInfo)]
Send ShowInfoBox (StrJoinFromArray(asInfo, C_CRLF)) "Results"
End_Procedure
WebPublishProcedure ProcessSecondAnswer // Publish the proc to receive control after second answer
// Is called in response to user's first answer:
Procedure ProcessFirstAnswer Integer eAnswer
stAllMyState tState
WebGet ptState to tState
Move (GetCurrentProcessId()) to tState.iProc2
Move (CurrentDateTime()) to tState.tmAnswered1
Move (If((eAnswer = cmYes), "Yes", "No")) to tState.sFirstAswer
WebSet ptState to tState
Send ShowYesNo Self (RefProc(ProcessSecondAnswer)) ;
("Do you REALLY want to do this? (Proc:" * String(tState.iProc2) + ")") ;
"Second question"
End_Procedure
WebPublishProcedure ProcessFirstAnswer // Publish the proc to receive control after first answer
// Triggers the question cascade:
Procedure OnClick
stAllMyState tState
Move (CurrentDateTime()) to tState.tmClicked
Move (GetCurrentProcessId()) to tState.iProc1
WebSet ptState to tState
Send ShowYesNo Self (RefProc(ProcessFirstAnswer)) ;
("Do you want to do this? (Proc:" * String(tState.iProc1) + ")") ;
"First question"
End_Procedure
End_Object
Object oDialog is a cWebButton
Set piColumnIndex to 4
Set piColumnSpan to 2
Set psCaption to "Popup Dialog"
Procedure OnCloseModalDialog Handle hoModalDialog
Integer iProc1 iProc2
If (hoModalDialog = oTestDialog) Begin
Send UpdateProcInfo
Get DialogResult of oTestDialog to iProc1
Move (GetCurrentProcessId()) to iProc2
Send ShowInfoBox ;
("Dialog in process" * ;
String(iProc1) + C_CRLF + ;
"Returned to process" * ;
String(iProc2)) "Result"
End
End_Procedure
Procedure OnClick
Send PopupTheDialog of oTestDialog Self (GetCurrentProcessId())
End_Procedure
End_Object
End_Object
End_Object
ProcPoolDemo.wo
Mike