How to Surface Errors in WebSnap and Still Retain Field Values.

概要: How to Surface Errors in WebSnap and Still Retain Field Values.

A common task in web applications is validating data whenever a user submits something to your site. In most cases the web application does some kind of processing on the data and either rejects the data, or hums along merrily.

In cases where the user enters invalid data it is often required to relate this problem back to the user. In some cases some of the data is correct and doesn't need to be reentered. From a user's standpoint it makes sense to retain field values that don't need to be modified.

WebSnap offers a way to validate the data and surface errors when they occur, as well as retain field values. This article will cover the steps necessary to perform such a task in Delphi. A sample program can be downloaded here.

Some knowledge of WebSnap would be advisable before reading this document. It is assumed that you know how to create AdapterFields and AdapterActions as well as how to incorporate them in the server script through the Web Page Editor.

You WebSnap application should have a WebModule with an AdapterPageProducer and Adapter on it. The Adapter will need at least one AdapterField and one AdapterAction. Once you have created an AdapterForm you should "Add Component" (to the AdapterForm) and add an AdapterErrorList. To validate the data we will put code in the Adapter's OnBeforeExecute event and add errors to the AdapterErrorList. This event fires before the AdapterAction's Execute method fires and provides a way to prevent the Execute method from executing all together. Below is a example of some code that would be executed in the OnBeforeExecute event:

procedure TSomeForm.Adapter1BeforeExecuteAction(Sender, Action: TObject;
  Params: TStrings; var Handled: Boolean);
begin
  //BeforeExecute is called each time an Action gets executed.
  //for this reason we have to check which action we are in and make sure it is the one we
  //want to validate.
  if TAdapterAction(Action).ActionName = 'adpActSubmit' then
  begin
    if (adpFldSomeInt.ActionValue <> nil) and (adpFldSomeInt.ActionValue.ValueCount > 0) then
    begin
      try
        //Simple check to see if field can be converted to an integer...
        StrToInt( adpFldSomeInt.ActionValue.Values[0] );
      except on E: Exception do
        begin
          //if there is an exception raised during the conversion then we can surface this
          //through our Adapter.Errors property
          Adapter1.Errors.AddError(
		 Format('%s is not an integer', [adpFldSomeInt.ActionValue.Values[0]]));
          //Next we would like to reflect the data that the user entered
          Adapter1.EchoActionFieldValues := True;
          //Finally stop the chain of events here to prevent the actual action from executing...
          Handled := True;
        end;
      end;
    end
    else
    begin
      Adapter1.Errors.AddError('Please enter an integer!');
      Adapter1.EchoActionFieldValues := True;
      Handled := True;
    end;
  end;
end;

In the example we tested the ActionValue of the adapter field to see if it was a valid integer. If for some reason the value couldn't be converted to an integer then an exception would have been raised. When we handle the exception we can add strings to the Adapter's Errors property and notify the user of their mistake(s).

The next step is to preserve the Field Values, which is done with the Adapter's EchoActionFieldValues property. Setting this property to True will display the values that were initially entered on the form the next time the user sees it.

Finally, the Handled property must be set to True if an error occurs. If this variable is set to False then the AdpaterAction's Execute method will be called. If this variable is set to True the chain of events stops after OnBeforeExecute has finished. Validation can be done from within the Execute method, however you will not be able to surface any errors. You'll also notice in the Adapter's OnBeforeExecute that a parameter named Action was passed in. This variable can be cast to a TAdapterAction and the ActionName can be retrieved. This is useful since OnBeforeExecute will fire for every Action and you may only want to perform certain checks for certain actions.

You will now be able to create web forms and validate the data.