Door Marek Musielak, 10/07/2026
Onlangs kwam ik een situatie tegen waarbij een Sitecore Forms submit action getriggerd moest worden op de Sitecore Content Delivery server, maar eigenlijk uitgevoerd moest worden op de Sitecore Content Management server. In mijn geval lag de reden bij netwerkbeperkingen; de Content Delivery servers konden een vereiste service simpelweg niet rechtstreeks bereiken. Om dit op te lossen, maakte ik gebruik van de Remote Event-functionaliteit van Sitecore. Herken je dit: je action heeft toegang nodig tot de master database, is afhankelijk van netwerkconnectiviteit die niet beschikbaar is vanaf CD, of is CPU-intensief waardoor je die belasting liever niet op de CD-servers legt; dan leg ik hieronder uit hoe je dit opzet.
De eerste stap is het aanmaken van een custom Sitecore Forms submit action class. De logica hierachter is eenvoudig: we maken een instance aan van de RemoteFormActionEvent class en voegen deze toe aan de EventQueue van de context database:
Contacteer ons
Netwerkbeperkingen, performance-bottlenecks, services die enkel bereikbaar zijn vanaf de CM-server; het stapelt zich op. Wil je hulp bij het uitwerken van een oplossing die wél werkt? Daar staan we voor klaar.
using Newtonsoft.Json;
using Sitecore;
using Sitecore.ExperienceForms.Models;
using Sitecore.ExperienceForms.Processing;
using Sitecore.ExperienceForms.Processing.Actions;
namespace MyAssembly.MyNamespace
{
public class RemoteFormAction : SubmitActionBase<object>
{
public RemoteFormAction(ISubmitActionData submitActionData) : base(submitActionData)
{
}
protected override bool Execute(object data, FormSubmitContext formSubmitContext)
{
var remoteEvent = new RemoteFormActionEvent(Sitecore.Configuration.Settings.InstanceName, "form:remoteaction")
{
FormSubmitContext = new LimitedFormSubmitContext(formSubmitContext),
Data = data
};
Context.Database.RemoteEvents.EventQueue.QueueEvent(remoteEvent);
return true;
}
protected override bool TryParse(string value, out object target)
{
target = JsonConvert.DeserializeObject(value);
return true;
}
}
}
We kunnen objecten van de Sitecore.ExperienceForms.Processing.FormSubmitContext class niet eenvoudig serialiseren en deserialiseren, dus gebruiken we in plaats daarvan een custom LimitedFormSubmitContext class:
using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.ExperienceForms.Models;
using Sitecore.ExperienceForms.Processing;
namespace MyAssembly.MyNamespace
{
public class LimitedFormSubmitContext
{
public LimitedFormSubmitContext()
{
}
public LimitedFormSubmitContext(FormSubmitContext context)
{
FormId = context.FormId;
PageId = context.PageId;
Fields = context.Fields;
Errors = context.Errors;
Canceled = context.Canceled;
}
public Guid FormId { get; set; }
public Guid PageId { get; set; }
public IList<IViewModel> Fields { get; set; } = new List<IViewModel>();
public IList<FormActionError> Errors { get; set; } = new List<FormActionError>();
public bool HasErrors => Errors.Any();
public bool Canceled { get; set; }
}
}
Onze RemoteFormActionEvent, die de IHasEventName interface implementeert, bevat extra properties voor de FormSubmitContext en Data objecten. Beide worden geserialiseerd met TypeNameHandling.All, waardoor ze correct kunnen worden gedeserialiseerd naar hun originele types; bijvoorbeeld de Fields property van de context, van het type IList<IViewModel>:
using Newtonsoft.Json;
using Sitecore.Eventing;
using System.Runtime.Serialization;
namespace MyAssembly.MyNamespace
{
[DataContract]
internal class RemoteFormActionEvent : IHasEventName
{
private static JsonSerializerSettings _settings;
private static JsonSerializerSettings Settings => _settings
?? (_settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
public RemoteFormActionEvent(string instanceName, string eventName)
{
InstanceName = instanceName;
EventName = eventName;
}
[DataMember]
public string InstanceName { get; protected set; }
[DataMember]
public string EventName { get; protected set; }
[IgnoreDataMember]
public LimitedFormSubmitContext FormSubmitContext { get; set; }
[IgnoreDataMember]
public object Data { get; set; }
[DataMember]
public string FormSubmitContextJson
{
get => FormSubmitContext == null ? null : JsonConvert.SerializeObject(FormSubmitContext, Settings);
set
{
if (!string.IsNullOrEmpty(value))
{
FormSubmitContext = JsonConvert.DeserializeObject<LimitedFormSubmitContext>(value, Settings);
}
}
}
[DataMember]
public string DataJson
{
get => Data == null ? null : JsonConvert.SerializeObject(Data, Settings);
set
{
if (!string.IsNullOrEmpty(value))
{
Data = JsonConvert.DeserializeObject<object>(value, Settings);
}
}
}
}
}
Vervolgens hebben we een Initialize pipeline processor nodig die zich abonneert op onze RemoteFormActionEvent:
using Sitecore.Data.Events;
using Sitecore.Eventing;
using Sitecore.Events;
using Sitecore.Pipelines;
namespace MyAssembly.MyNamespace
{
public class SubscribeToExecuteFormRemoteActionEvent
{
public void Initialize(PipelineArgs args)
{
EventManager.Subscribe<RemoteFormActionEvent>(OnRemoteEvent);
}
private static void OnRemoteEvent<TEvent>(TEvent @event) where TEvent : IHasEventName
{
var remoteEventArgs = new RemoteEventArgs<TEvent>(@event);
Event.RaiseEvent(@event.EventName, remoteEventArgs);
}
}
}
Het laatste onderdeel is een RemoteFormActionEventHandler, die de verwerking van de data op de Sitecore Content Management server afhandelt. Hier kun je doen wat je nodig hebt met de formuliergegevens. In mijn geval log ik de informatie eenvoudigweg om te bevestigen dat de juiste instance de code uitvoert en dat alle benodigde data succesvol is doorgegeven vanaf de Content Delivery server:
using System;
using Newtonsoft.Json;
using Sitecore.Data.Events;
using Sitecore.Diagnostics;
namespace MyAssembly.MyNamespace
{
public class RemoteFormActionEventHandler
{
public void HandleRemote(object sender, EventArgs args)
{
var eventArgs = args as RemoteEventArgs<RemoteFormActionEvent>;
if (eventArgs == null)
return;
ExecuteAction(eventArgs.Event.Data, eventArgs.Event.FormSubmitContext);
}
private void ExecuteAction(object data, LimitedFormSubmitContext formSubmitContext)
{
Log.Info($"HandleRemote called on '{Sitecore.Configuration.Settings.InstanceName}'" +
$" with data '{JsonConvert.SerializeObject(data)}' " +
$"and context '{JsonConvert.SerializeObject(formSubmitContext)}'", this);
}
}
}
De laatste stap is de configuratie. Op de Sitecore Content Management server registreren we een event en processor:
<configuration xmlns:role="http://www.sitecore.net/xmlconfig/role/">
<sitecore role:require="ContentManagement">
<events>
<event name="form:remoteaction">
<handler type="MyAssembly.MyNamespace.RemoteFormActionEventHandler, MyAssembly" method="HandleRemote" />
</event>
</events>
<pipelines>
<initialize>
<processor
type="MyAssembly.MyNamespace.SubscribeToExecuteFormRemoteActionEvent, MyAssembly" method="Initialize" />
</initialize>
</pipelines>
</sitecore>
</configuration>
Deze aanpak maakt het mogelijk om Sitecore Forms submit actions uit te voeren op de Content Management server in plaats van op Content Delivery. Het is een handige oplossing wanneer CD-servers de vereiste services niet kunnen bereiken, of wanneer je die workload simpelweg liever van de CD-instances weghoudt.
Laten we het over Sitecore-architectuur hebben
Krijg deskundig advies over het optimaliseren van je Sitecore-opzet
Of het nu gaat om het weghalen van workload van Content Delivery, het oplossen van netwerkbeperkingen of het verbeteren van de algemene performance, ons team helpt je de juiste aanpak te vinden. Vul het formulier in en we nemen contact met je op.