Exam Area: Content Area 5 – Content Models (25%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/optimizely-forms
Optimizely Forms is an add-on that lets editors create forms through a drag-and-drop UI without writing code. Forms can:
# NuGet package
dotnet add package EPiServer.Forms
// Program.cs
builder.Services.AddOptimizelyForms();
// or in IConfigurableModule
services.AddOptimizelyForms(options =>
{
options.MaxFileSizeInBytes = 1024 * 1024; // 1MB
});
FormContainerBlock (root)
├── Step 1 (FormStepBlock)
│ ├── TextboxElementBlock (Name)
│ ├── TextboxElementBlock (Email)
│ └── TextareaElementBlock (Message)
├── Step 2 (FormStepBlock)
│ ├── FileUploadElementBlock
│ └── CheckboxElementBlock (GDPR consent)
└── Submit (SubmitButtonElementBlock)
| Element | Type | Description |
|---|---|---|
TextboxElementBlock | Text input | Short text field |
TextareaElementBlock | Textarea | Multi-line text |
DropdownElementBlock | Dropdown | Single select |
CheckboxElementBlock | Checkbox | Boolean |
ChoiceElementBlock | Radio/Checkbox group | Multiple options |
FileUploadElementBlock | File upload | Upload files |
HiddenElementBlock | Hidden field | Hidden value |
NumberElementBlock | Number input | Numeric |
DateTimeElementBlock | Date picker | Date/time |
SelectionElementBlock | Select list | From predefined options |
SubmitButtonElementBlock | Submit button | Submit form |
FormStepBlock | Step container | Multi-step form |
FormContainerBlock | Form root | Contains all elements |
@* In page view *@
@using EPiServer.Forms.Helpers.Internal
@if (Model.CurrentPage.ContactForm != null)
{
@Html.PropertyFor(m => m.CurrentPage.ContactForm)
}
@* Or render directly *@
@{
var formContent = _contentLoader.Get<FormContainerBlock>(formReference);
}
@Html.RenderEPiServerForms(formContent, ViewContext)
// IFormDataRepository - reads form submissions
public class FormDataService
{
private readonly IFormDataRepository _formDataRepository;
public FormDataService(IFormDataRepository formDataRepository)
{
_formDataRepository = formDataRepository;
}
public IEnumerable<FormIdentity> GetFormSubmissions(Guid formGuid)
{
return _formDataRepository.GetSubmissions(formGuid);
}
}
// Create custom form element
[ContentType(
DisplayName = "Rating Element",
GUID = "...",
GroupName = "Form Elements")]
public class RatingElementBlock : ElementBlockBase
{
[Display(Name = "Max rating")]
[Range(1, 10)]
public virtual int MaxRating { get; set; }
[Display(Name = "Label")]
public virtual string Label { get; set; }
// ElementName is required for form submission
public override string Label => this.LocalLabel;
}
// Subscribe to form submission events
[InitializableModule]
public class FormEventHandler : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
FormsEvents.Instance.FormsSubmitting += OnFormsSubmitting;
FormsEvents.Instance.FormsSubmissionFinalized += OnFormsSubmitted;
}
public void Uninitialize(InitializationEngine context)
{
FormsEvents.Instance.FormsSubmitting -= OnFormsSubmitting;
FormsEvents.Instance.FormsSubmissionFinalized -= OnFormsSubmitted;
}
private void OnFormsSubmitting(object sender, FormsSubmittingEventArgs e)
{
// Before submit - can cancel
var formData = e.SubmissionData;
// Validate custom logic
if (!ValidateSubmission(formData))
{
e.CancelAction = true;
e.CancelReason = "Validation failed";
}
}
private void OnFormsSubmitted(object sender, FormsSubmittedEventArgs e)
{
// After submit - integrate with external systems
var submissionId = e.SubmissionId;
ExternalCRM.SendLead(e.SubmissionData);
}
}
// Form Actor - runs after submit
public class CrmIntegrationActor : IFormActor
{
public string Key => "CrmIntegration";
public string DisplayName => "Send to CRM";
public Task<object> RunAsync(IFormActorData formActorData)
{
var email = formActorData.SubmissionData
.FieldData.FirstOrDefault(f => f.Name == "Email")?.Value;
// Send to CRM
CrmService.CreateLead(email);
return Task.FromResult<object>(null);
}
}
EPiServer.Forms)FormContainerBlock? (The root block containing the entire form and its steps)IFormDataRepository do? (Reads/queries form submissions)