Adding A Server-Side Notification Handler To Umbraco Forms
See an example of validating a form server-side
Form validation notification
Add a new class to your project as a handler for the FormValidateNotification notification:
usingSystem.Linq;usingMicrosoft.AspNetCore.Http;usingUmbraco.Cms.Core.Events;usingUmbraco.Forms.Core.Models;usingUmbraco.Forms.Core.Services.Notifications;namespaceMyFormsExtensions{ /// <summary> /// Catch form submissions before being saved and perform custom validation. /// </summary>publicclassFormValidateNotificationHandler:INotificationHandler<FormValidateNotification> {publicvoidHandle(FormValidateNotification notification) { // If needed, be selective about which form submissions you affect.if (notification.Form.Name=="Form Name") { // Check the ModelStateif (notification.ModelState.IsValid==false) {return; } // A sample validationvar email =GetPostFieldValue(notification.Form,notification.Context,"email");var emailConfirm =GetPostFieldValue(notification.Form,notification.Context,"verifyEmail"); // If the validation fails, return a ModelErrorif (email.ToLower() !=emailConfirm.ToLower()) { notification.ModelState.AddModelError(GetPostField(notification.Form, "verifyEmail").Id.ToString(), "Email does not match");
} } }privatestaticstringGetPostFieldValue(Form form,HttpContext context,string key) {Field field =GetPostField(form, key);if (field ==null) {returnstring.Empty; }returncontext.Request.HasFormContentType&&context.Request.Form.Keys.Contains(field.Id.ToString())?context.Request.Form[field.Id.ToString()].ToString().Trim():string.Empty; } private static Field GetPostField(Form form, string key) => form.AllFields.SingleOrDefault(f => f.Alias == key);
}}
The handler will check the ModelState and Form field values provided in the notification. If validation fails, we add a ModelError.
To register the handler, add the following code into the startup pipeline. In this example, the registration is implemented as an extension method to IUmbracoBuilder and should be called from Program.cs:
The services available via interfaces IFormService, IFolderService, IDataSourceService and IPrevalueSourceService trigger following notifications before or after an entity handled by the service is modified.
The "-ing" events allow for the entity being changed to be modified before the operation takes place, or to cancel the operation. The "-ed" events fire after the update is complete.
Both can be wired up using a composer and component:
When a form or folder is moved there is no specific service event. However, information available in the State dictionary on the notification object can be used to determine whether the item was moved. If so, it can show where it was moved from:
If a folder is being moved, the key within the State dictionary is "MovedFromParentId".
Backoffice entry rendering events
When an entry for a form is rendered in the backoffice, an event is available to allow modification of the record detail. This event is available before the record details are presented to the user. This is shown in the following example:
publicclassTestSiteComposer:IComposer {publicvoidCompose(IUmbracoBuilder builder) { builder.AddNotificationHandler<EntrySearchResultFetchingNotification, EntrySearchResultFetchingNotificationHandler>();
} } public class EntrySearchResultFetchingNotificationHandler : INotificationHandler<EntrySearchResultFetchingNotification>
{ public voidHandle(EntrySearchResultFetchingNotification notification) {var transformedFields =newList<object>();foreach (var field innotification.EntrySearchResult.Fields) {if (field?.ToString() =="Test") {transformedFields.Add("Test (updated)"); }else {transformedFields.Add(field); } }notification.EntrySearchResult.Fields= transformedFields; } }