TPC Form Submission Events

Sometimes actions need to be performed on user-submitted data before or after the form has been submitted. These types of actions can be performed server-side or client-side in the web browser. 

Server-side events

Server-side events happen on the web server and are written in C#. To use them you must have access to the Sitefinity application code, Visual Studio and be knowledgeable in C#. There are 2 events server that a developer can use to perform action with the submitted form data: ITpcPreMvcFormSubmitEvent and ITpcPostMvcFormSubmitEvent

The ITpcPreMvcFormSubmitEvent event fires before the form data is sent to CRM. This event gives access to the Entity being submitted as well as the connection to CRM. With this information, a developer can adjust the data, run additional checks, lookup related data, or send the data elsewhere as required. After any custom code finishes executing, the entity is then sent to the configured instance of CRM.

The ITpcPostMvcFormSubmitEvent event fires after the form data has been sent to CRM. This event gives to the submitted entity as it was sent to CRM, any child entities submitted and the connection to CRM. As with the pre-submit event, you can then use the returned information to perform any additional actions required.

Server-side code

When writing event handlers on the server-side, it is important to subscribe your handlers after Sitefinity has been “Bootstrapped”. Bootstrapped is when the application is setting up anything required for the application to function correctly. In order to be sure that the application in the correct state to subscribe your event handlers, the following code can be added to the Global.asax.cs file within the Sitefinity Application in Visual Studio. This file contains a number of events that fire in response to various conditions in the application. The one we are interested in is Application_Start which fires as the application is starting up. Below it we add a new method (Bootstrapper_Initialized) to check the current start-up status and subscribe to the events when appropriate. Then we attach it to the Sitefinity Bootstrapper.Initialized event. When the application starts, the Application_Start event fires, attaches our method which then sets up our event handlers. While you can put your event handlers virtually anywhere in the application, it is important to subscribe to them as shown below to ensure that the application is in the correct state to allow the handlers to be subscribed to. 

Code Example 1: Subscribing to events

protected void Application_Start(object sender, EventArgs e) {     Bootstrapper.Initialized += Bootstrapper_Initialized; } void Bootstrapper_Initialized (object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e) {     if (e.CommandName == "Bootstrapped")     {         EventHub.Subscribe<ITpcPreMvcFormSubmitEvent>(PreFormSubmitEventHandler);         EventHub.Subscribe<ITpcPostMvcFormSubmitEvent>(PostFormSubmitEventHandler);     } }

In the above example, the ITpcPreMvcFormSubmitEvent and ITpcPostMvcFormSubmitEvent events are being subscribed to by passing the name of a function to the Subscribe function. The actual handlers it is referring to are shown below.

Code Example 2: Sample ITpcPreMvcFormSubmitEvent Handler

private void PreFormSubmitEventHandler(ITpcPreMvcFormSubmitEvent @event) {     // Connection to CRM.      ICrmConnection connection = @event.Connection;     // Entity that will be submitted to CRM.      Entity submissionEntity = @event.SubmissionEntity;     /*         Your code goes here...     */ }

Example 2 is one of the functions referenced in example 1. As noted, it contains the connection to CRM and the Entity that will be submitted to CRM. If this entity is changed in the event handler, it will be submitted to CRM in its modified form. This allows you to make changes outside of the users input and have those changes sent to CRM. This event can fire more than once if the submitted for has more than one entity configured (I.E. Nested Form Configuration Widgets configured for different entities.)

Code Example 3: Sample ITpcPostMvcFormSubmitEvent Handler

private void PostFormSubmitEventHandler(ITpcPostMvcFormSubmitEvent @event) {     // Connection to CRM.      ICrmConnection connection = @event.Connection;     // Entity that was submitted to CRM.      Entity submissionEntity = @event.SubmittedEntity;     // Additional Child Entities submitted to CRM.     IList<Entity> childEntities = @event.ChildEntities;     /*         Your code goes here...     */ }

Example 3 is the other function referenced in example 1. It also contains the connection to CRM as well as the entity as it was submitted to CRM and any child entities that were submitted. If the submission fails, this event will not fire. Additionally, the entities returned are as they were submitted. If this data is changed on the CRM server once submitted (In a workflow, for example), those changes to the entity will not be reflected in the returned entities. In this case you can use the provided Connection and SubmittedEntity properties to retrieve them from CRM.

Client-side events

Client-side events happen in the web browser of the user. Unlike server-side events which are written in C#, client-side events are written in JavaScript. While server-side events require access to the source code of the site, client-side event handlers can be created in a number of places including in a JavaScript form or page widget, page template or an external .js file.

On the client-side, there are as 4 events:

  • tpc:pre-validate
  • tpc:pre-submit
  • tpc:post-submit
  • tpc:invalid.

The tpc:pre-validate event fires before the form data is validated. This gives you the opportunity to perform custom validation and return an error message when needed. This event gives access to 3 objects:  event, form and sender.

  • event gives access to the event which contains information relating to the event that was just fired.
  • form gives access to the form itself.
  • sender gives access to the button that was clicked to submit the form. If the button is a TPC submit button, you will get the same object as the TPC front end API and it it is a Sitefinity submit button, you will get a jQuery object for the button.
To prevent further events from firing after this event, set an error message in event.message and return false.

The tpc:pre-submit event fires before the form data is sent to CRM. This event gives access to 4 objects: event, form, formData and sender.

  • event gives access to the event which contains information relating to the event that was just fired.
  • form gives access to the form itself.
  • formData contains the data contained in the form. formData is a standard formData object which is documented at https://developer.mozilla.org/en/docs/Web/API/FormData
  • sender gives access to the button that was clicked to submit the form. If the button is a TPC submit button, you will get the same object as the TPC front end API and it it is a Sitefinity submit button, you will get a jQuery object for the button.

To prevent further events from firing after this event, set an error message in event.message and return false.

The tpc:post-submit event fires after the form has been submitted and receives a response from the server. It gives access to 4 objects: event, form, request and sender.

  • event gives access to the event which contains information relating to the event that was just fired.
  • form gives access to the form itself.
  • sender gives access to the button that was clicked to submit the form. If the button is a TPC submit button, you will get the same object as the TPC front end API and it it is a Sitefinity submit button, you will get a jQuery object for the button.

The tpc:invalid event fires if the form fails validation. Empty required fields are a good example of what triggers this event. When tpc:invalid event fires, the tpc:pre-submit event will not fire. This event gives access to 3 objects: event, formContainer and sender.

  • event gives access to the event which contains information relating to the event that was just fired.
  • formContainer gives access to the container of the form being submitted. From here you can access all the form fields and determine the invalid fields.
  • request contains information about the request. Its contents can vary depending if the request was successful.
  • sender gives access to the button that was clicked to submit the form. If the button is a TPC submit button, you will get the same object as the TPC front end API and it it is a Sitefinity submit button, you will get a jQuery object for the button.

Client-side code

Implementing event handlers on the client side can be done is a number of places but the simplest is to write your handler within the JavaScript form or page widget. To do this simply drag the JavaScript widget onto your page or form then click its Edit link. From here you add the code needed to subscribe to and define the handler.

The following 4 code examples can be entered into the code area of the widget. As examples they simply log the objects provided by the event to the developer console of the web browser where you can see the data returned.

Code Example 4: Sample tpc:pre-validate Handler

$(document).on("tpc:pre-validate", function (event, form, sender) {
    console.log("tpc:pre-submit event:", event);
    console.log("tpc:pre-submit form:", form);
    console.log("tpc:pre-submit sender:", sender);
    event.message = "This is an error from \"tpc:pre-validate\"";
    return false;
});

Code Example 5: Sample tpc:invalid Handler

$(document).on("tpc:invalid", function (event, formContainer, sender) {
    console.log("tpc:invalid event:", event);
    console.log("tpc:invalid: formContainer:", formContainer);
    console.log("tpc:invalid sender:", sender);
});

Code Example 6: Sample tpc: pre-submit Handler

$(document).on("tpc:pre-submit", function (event, form, formData, sender) {     
    console.log("tpc:pre-submit event:", event);
    console.log("tpc:pre-submit form:", form);
    console.log("tpc:pre-submit formData:", formData);
    console.log("tpc:pre-submit sender:", sender);
    event.message = "This is an error from \"tpc:pre-submit\"";
    return false;
});

Code Example 7: Sample tpc: post-submit Handler

$(document).on("tpc:post-submit", function (event, form, request, sender) {
    console.log("tpc:post-submit event:", event);
    console.log("tpc:post-submit form:", form);
    console.log("tpc:post-submit request:", request);
    console.log("tpc:post-submit sender:", sender);
});

Differences between Server-side and Client-side events

The primary difference between the server and client-side events, beyond where the event executes is the data each event provides access to. On the client-side, the data is form data. It will contain information relating to the entity type and such but does not know anything beyond the form configuration. It is simply form data. On the server-side things are different. When server-side events fire, the data provided from the form has been converted to a CRM entity. Working with server-side events allows you to manipulate the entity directly where on the client -side, you can manipulate the data before it is converted to an entity.

Order of events

Events fire in the following order:

  1. User clicks submit button.
  2. Client-side: tpc:pre-validate event fires.
    1. If false is returned
      1. event.message is displayed and no further events fire.
  3. Form is validated
    1. If invalid
      1. Client-side: tpc:invalid event fires and no additional events fire.
  4. Client-side: tpc:pre-submit event fires.
    1. If false is returned
      1. event.message is displayed and no further events fire.
  5. Server-side: ITpcPreMvcFormSubmitEvent event fires.
  6. Server-side: ITpcPostMvcFormSubmitEvent event fires.
  7. Client-side: tpc:post-submit event fires.