Skip to content

Web Application Flow

Related topics: - Web Properties Methods and Events - Positioning and Layout of Controls

Overview

A Web Application works differently than a traditional desktop application. The client (your browser) does not own a single persistent instance of the WebApp process. Instead, the server maintains a pool of WebApp.exe processes. When a client needs a process, it connects to one from the pool, initializes and synchronizes it with data from the client, processes requests, then disconnects and returns the process to the pool.

Starting an Application Process

When your Web Application starts, a number of WebApp.exe processes are loaded and initialized. The number of processes created depends on your process pooling settings. (You generally should use process pooling.) This startup creates all of your objects, sets their default properties, and places the process into the pool.

Important points about this initialization:

  • During initialization you are not connected to a client. You are starting a default instance that might be used by any client and by multiple clients.
  • Because you are not connected to a client, do not use WebSet/WebGet to configure web-properties during initialization. Use Get and Set to establish default values that will apply to all clients.
  • Attempting to WebSet a property during initialization will cause a runtime error.
  • WebGet during initialization acts like Get and returns default values. Prefer Get during initialization unless you explicitly need the web-property behavior.
  • If an error occurs during initialization there is no client/browser present to handle it; such errors are considered fatal. Under the debugger you will see the error in the debug’s error display. At deployment, startup errors are logged to the Windows event log.
  • Every object you create and every property you set during initialization defines the default environment for clients when they first connect. Subsequent changes are stored as web-properties and synchronized between client and server as needed.

Starting a Web Application in your Browser

The URL you open in your browser (for example http://MySite/MyApplication/Index.html) loads a page that contains the JavaScript classes required to run the application and an AJAX-style request handler. From that point the page is not reloaded; all communication is via AJAX-style requests. These requests create browser sessions, display the main application, load views and dialogs, and handle client interactions.

WebApp Client-to-Server Requests

Requests are performed through web-service calls using JSON. This request/response cycle is often called a "round trip to the server". You can view each request/response in your browser’s debugger (for example with Firebug or the browser network console).

Common request types:

  • Load the WebApp — starts a new browser session and displays the application shell (menus, toolbars, login, and possibly an initial view).
  • Load a new view/dialog — when the view/dialog has not yet been loaded on the client; the server sends the definition so the client can initialize it.
  • Show a view/dialog — when the view/dialog is already present in the client; often no server request is required unless configured to do so.
  • Interact with a view/dialog — when a client action requires server interaction (e.g., finding, saving, deleting records).

Common behavior for all requests:

  • Each request attaches to the next available process in the pool. Do not assume a persistent one-to-one connection between a browser and a process.
  • Each request must initialize the instance based on data passed from the browser. The framework synchronizes all web-properties and the state of DDO structures and controls for views/dialogs involved in the request.
  • Requests are serviced by calling server-side events (e.g., OnClick) or server actions (e.g., RequestSave).
  • Handlers and methods called during requests primarily interact with web-properties. Use WebGet and WebSet during request processing rather than Get/Set.
  • Some server-side events are optional, enabled or disabled using properties such as pbOnServerEventName (e.g., pbServerOnShow).
  • If no server-side events are required for a view change, the operation may occur without a server request (for example, if pbServerOnShow is False on the new view and pbServerOnHide is False on the old view).
  • Low-level attach/detach events, OnAttachProcess and OnDetachProcess, occur for every request. These are triggered before and after synchronization respectively and should not normally be augmented. Do not use WebGet/WebSet in these events.
  • Only the views and dialogs that are part of the request are synchronized on the server — this may be a single view, two views (switching), or a view with modal dialogs. The framework determines which views/dialogs need synchronization.

Typical request flow

Most requests sent to a view or dialog follow this outline:

  1. OnAttachProcess is sent to the cWebApp object.
  2. Synchronize all web-properties.
  3. OnSyncWebApp is sent to your cWebApp object.
  4. For each view that needs to be synchronized:
  5. Check AllowAccess.
  6. Rebuild_Constraints is sent to all DDOs in the view's main DDO structure.
  7. Synchronize the main DDO structure.
  8. OnSyncView is sent to the view.
  9. Process all request actions.
  10. Build the response data.
  11. OnDetachProcess is sent to the cWebApp object.

Note: - OnSyncWebApp is sent to the main cWebApp before view synchronization and is useful for global customizations and rights handling. - If a view’s AllowAccess returns False, the request is canceled for security reasons. - OnSyncView is sent to each view/dialog used in the request and is useful for rights handling and defining dynamic constraints in the view’s DDO structure. Typically, define custom DDO OnConstrain logic based on web-properties. - After OnSyncView, Rebuild_Constraints is sent to your DDO structure, so explicit manual rebuild is not required when customizations occur inside OnSyncView. - The "process all request actions" step may include actions like loading or hiding views, which can trigger additional events (for example OnClick). - If you change constraints outside of the Rebuild_Constraints process (for example in another event), you must send Rebuild_Constraints to the relevant DDOs. - Test the value returned by AppSynching in any data dictionary events that may be triggered during a find operation (e.g., OnPostFind, Refresh, OnNewCurrentRecord). AppSynching (see cWebApp::AppSynching) returns True while the framework is synchronizing web-properties and DDO structure, and False while processing request actions. Normally you do not want to process DDO events when AppSynching returns True.

Action — Loading a WebApp

The first time a client requests a WebApp, the server must load the WebApp onto the client. Steps:

  1. CreateSession — create a new session.
  2. Clear all web-properties.
  3. Send OnChangeRights to the cWebApp object, the command bar, and all of its objects.
  4. Serialize all web-objects to be displayed (sent to the client and converted to client-side objects). Typically this includes the main cWebApp object, menus, and toolbars.
  5. Send OnLoad to every serialized web-object.
  6. If a default login or default view is defined, load it (see Action — Loading a View/Dialog).

Note: - OnChangeRights is sent during the load and when a user’s rights change (for example after login). It is sent to every menu object and can be used to enable/hide items, toolbars, menus, or the entire command bar system. - OnLoad is sent for every web-object when it is serialized and usually occurs only once per session.

Action — Loading a View or Dialog

The first time a view or dialog is requested, the view’s object definition must be serialized and sent to the client so it can display the view. Once loaded, the client can hide and reshow these views without needing the definition again.

Typical sequence when loading a view/dialog (including when replacing an existing view or opening a modal dialog):

  1. Check AllowAccess of the view.
  2. Send Clear_All to the view’s main DDO.
  3. OnSyncView.
  4. Serialize all web-objects to be displayed (sent to the client and converted to client-side objects).
  5. Send OnLoad to every serialized web-object.
  6. OnHide is sent to the old view (if there is an old view and pbServerOnHide is True).
  7. OnShow is sent to the new view (if pbServerOnShow is True).

Notes: - If a view’s AllowAccess returns False, the request is canceled for security. - OnLoad is usually only sent once per session for each object. - If there was an old view, that view will already have been synchronized as part of the normal request synchronization process.

Action — Showing a View or Dialog Already Loaded

When both the old and new views are already loaded:

  • OnHide is sent to the old view (if there is an old view and pbServerOnHide is True).
  • OnShow is sent to the new view (if pbServerOnShow is True).

If both views are already synchronized and pbServerOnHide / pbServerOnShow are False, there may be no server request at all.

Important Events

OnLoad

`OnLoad` is sent to every web-object when the object is loaded (serialized and sent to the client). This generally occurs once per session per object. `OnLoad` is sent unconditionally — there is no `pbServerOnLoad`.

Example: use `OnLoad` in a view to display a default record:

```dataflex
Procedure OnLoad
    Send Find of OrderHea_DD FIRST_RECORD Index.1
End_Procedure
```

Example: use `OnLoad` in `cWebApp` for first-time processing (e.g., automatic login):

```dataflex
Procedure OnLoad
    Boolean bOk
    Get UserLogin of ghoWebSessionManager "guest" "Guest" to bOk
End_Procedure
```

OnShow

OnShow is sent to a view or dialog when it is being shown. It is sent when the view is first loaded and each time it is re-displayed. OnShow is only called if pbServerOnShow is True. Useful for modal dialogs that require initialization each time they are shown.

OnHide ~~~~~~

OnHide is sent to a view or dialog when it is being hidden (for example, when another view is shown or when a modal dialog is closed). OnHide is only called if pbServerOnHide is True.

OnChangeRights ~~~~~~~~~~~~~~

OnChangeRights is sent whenever user rights change. It is sent to the cWebApp object, the command bar object, and all objects within the command bar. It is not sent to views; use OnSyncView to handle view-specific rights and role requirements.

OnSyncWebApp ~~~~~~~~~~~~

OnSyncWebApp is sent to the cWebApp object with each request after web-properties are synchronized but before any view DDOs are synchronized. Use it for global initializations and rights/role handling.

OnSyncView ~~~~~~~~~~

OnSyncView is sent to each view that needs synchronization during a request. It is sent after web-properties, DDOs, and DEOs are synchronized.

This event is important for controlling user rights, disabling/hiding controls, and initializing dynamic constraints. Use WebGet/WebSet for web-properties inside OnSyncView. If you change constraints in OnSyncView, call Rebuild_Constraints on the DDO so OnConstrain is applied.

Examples: two methods to customize DDO constraints

1) Use OnSyncView to read web-properties and set DDO properties, then call Rebuild_Constraints:

```dataflex Object oCustomerGrid is a cWebView { WebProperty = True } Property String psFilter "" { WebProperty = True } Property String psFilterFrom "" { WebProperty = True } Property String psFilterTo "" Procedure OnSyncView String sFilter sFrom sTo WebGet psFilter of oCustomerGrid to sFilter WebGet psFilterFrom of oCustomerGrid to sFrom WebGet psFilterTo of oCustomerGrid to sTo Set psType of oCustomer_DD to sFilter Set psFrom of oCustomer_DD to sFrom Set psTo of oCustomer_DD to sTo Send Rebuild_Constraints of oCustomer_DD End_Procedure

Object oCustomer_DD is a Customer_DataDictionary
    Property String psType
    Property String psFrom
    Property String psTo
    Procedure OnConstrain
        String sFilter sFrom sTo
        Forward Send OnConstrain
        Get psType to sFilter
        Get psFrom to sFrom
        Get psTo to sTo
        If (sFilter = "NUMBER") Begin
            Constrain Customer.Customer_Number Between sFrom and sTo
        End
        If (sFilter = "NAME") Begin
            Constrain Customer.Name Between sFrom and sTo
        End
    End_Procedure
End_Object

End_Object ```

2) Use web-properties directly in OnConstrain so no OnSyncView augmentation is required. Rebuild_Constraints will still call OnConstrain:

```dataflex Object oCustomerGrid is a cWebView { WebProperty = True } Property String psFilter "" { WebProperty = True } Property String psFilterFrom "" { WebProperty = True } Property String psFilterTo "" End_Object

Object oCustomer_DD is a Customer_DataDictionary Procedure OnConstrain String sFilter sFrom sTo Forward Send OnConstrain WebGet psFilter of oCustomerGrid to sFilter WebGet psFilterFrom of oCustomerGrid to sFrom WebGet psFilterTo of oCustomerGrid to sTo If (sFilter = "NUMBER") Begin Constrain Customer.Customer_Number Between sFrom and sTo End If (sFilter = "NAME") Begin Constrain Customer.Name Between sFrom and sTo End End_Procedure End_Object ```

Previous Topic: Web Properties Methods and Events
Next Topic: Positioning and Layout of Controls

See Also