Sitecore 10 Forms自定义提交动作CD服务器无法写入Master库求助
Sitecore Forms 跨库提交(CD→Master→Web)完整实现示例
核心思路
利用Sitecore EventQueue实现CD端无直接Master访问权限下的数据流转:CD端提交动作发布事件→CM端监听事件并写入Master→CM端自动发布数据到Web→触发邮件通知。
1. 自定义事件类(序列化传递表单数据)
using Sitecore.Data; using Sitecore.Eventing; using System; using System.Runtime.Serialization; [DataContract] public class ContactFormSubmissionEvent : Event { [DataMember] public string FormData { get; set; } [DataMember] public ID FormItemId { get; set; } [DataMember] public DateTime SubmissionTime { get; set; } }
2. CD端表单提交动作(发布事件)
using Sitecore.Diagnostics; using Sitecore.ExperienceForms.Models; using Sitecore.ExperienceForms.Processing; using Sitecore.ExperienceForms.Processing.Actions; using Sitecore.Eventing; using System; using System.Linq; using System.Text.Json; public class SubmitContactFormAction : SubmitActionBase<string> { private readonly IEventManager _eventManager; public SubmitContactFormAction(ISubmitActionData submitActionData, IEventManager eventManager) : base(submitActionData) { _eventManager = eventManager; } protected override bool TryParse(string value, out string result) { result = value; return true; } protected override bool Execute(string data, FormSubmitContext formSubmitContext) { try { // 序列化表单字段数据 var formFields = formSubmitContext.Fields .Select(f => new { f.Name, f.Value }) .ToList(); var serializedData = JsonSerializer.Serialize(formFields); // 构建事件对象 var submissionEvent = new ContactFormSubmissionEvent { FormData = serializedData, FormItemId = formSubmitContext.FormItemId, SubmissionTime = DateTime.UtcNow }; // 发布事件(Sitecore自动路由到CM的EventQueue) _eventManager.RaiseEvent(submissionEvent); Log.Info($"Form submission event published: FormID={formSubmitContext.FormItemId}", this); return true; } catch (Exception ex) { Log.Error($"Failed to publish submission event: {ex.Message}", ex, this); formSubmitContext.Errors.Add(new FormError("提交失败,请稍后重试", null)); return false; } } }
3. CM端事件处理程序(写入Master+发布+发邮件)
using Sitecore.Configuration; using Sitecore.Data; using Sitecore.Data.Items; using Sitecore.Diagnostics; using Sitecore.Eventing; using Sitecore.Publishing; using System; using System.Text.Json; using System.Net.Mail; public class ContactFormSubmissionHandler { // 替换为你的提交数据存储文件夹ID和模板ID private readonly ID _submissionsFolderId = new ID("{YOUR_SUBMISSIONS_FOLDER_ID}"); private readonly ID _submissionTemplateId = new ID("{YOUR_SUBMISSION_TEMPLATE_ID}"); public void OnContactFormSubmission(object sender, EventArgs args) { if (args is not EventNotificationEventArgs notificationArgs) return; var submissionEvent = notificationArgs.Event as ContactFormSubmissionEvent; if (submissionEvent == null) { Log.Warn("Received invalid form submission event", this); return; } try { var masterDb = Factory.GetDatabase("master"); if (masterDb == null) { Log.Error("Master database unavailable", this); return; } // 1. 写入Master数据库 var submissionsFolder = masterDb.GetItem(_submissionsFolderId); if (submissionsFolder == null) { Log.Error($"Submissions folder not found: {_submissionsFolderId}", this); return; } // 创建新提交项 var newSubmission = submissionsFolder.Add( $"Submission_{DateTime.UtcNow:yyyyMMddHHmmssfff}", new TemplateID(_submissionTemplateId) ); // 填充字段 var formData = JsonSerializer.Deserialize<dynamic>(submissionEvent.FormData); newSubmission.Editing.BeginEdit(); foreach (var field in formData) { var fieldName = field.Name.ToString(); if (newSubmission.Fields[fieldName] != null) { newSubmission.Fields[fieldName].Value = field.Value.ToString(); } } newSubmission.Fields["SubmissionTime"].Value = DateUtil.ToIsoDate(submissionEvent.SubmissionTime); newSubmission.Fields["FormItemId"].Value = submissionEvent.FormItemId.ToString(); newSubmission.Editing.EndEdit(); Log.Info($"Submission saved to Master: {newSubmission.ID}", this); // 2. 发布到Web数据库 PublishSubmissionItem(newSubmission); // 3. 发送通知邮件 SendNotificationEmail(formData, newSubmission.ID.ToString()); } catch (Exception ex) { Log.Error($"Failed to process submission event: {ex.Message}", ex, this); } } private void PublishSubmissionItem(Item item) { var webDb = Factory.GetDatabase("web"); var publishOptions = new PublishOptions( item.Database, webDb, PublishMode.SingleItem, item.Language, DateTime.Now ); var publisher = new Publisher(publishOptions); publisher.Options.RootItem = item; publisher.Options.Deep = false; publisher.Publish(); Log.Info($"Submission published to Web: {item.ID}", this); } private void SendNotificationEmail(dynamic formData, string submissionId) { try { var mail = new MailMessage { From = new MailAddress("noreply@yourdomain.com"), To = { "admin@yourdomain.com" }, Subject = $"新表单提交 - ID: {submissionId}", IsBodyHtml = true }; var body = "<h3>新表单提交详情</h3><ul>"; foreach (var field in formData) { body += $"<li><strong>{field.Name}:</strong> {field.Value}</li>"; } body += $"<li><strong>提交ID:</strong> {submissionId}</li></ul>"; mail.Body = body; using var smtpClient = new SmtpClient(); smtpClient.Send(mail); Log.Info($"Notification email sent for submission: {submissionId}", this); } catch (Exception ex) { Log.Error($"Failed to send notification email: {ex.Message}", ex, this); } } }
4. 配置补丁(注册事件与处理程序)
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <events> <event name="ContactFormSubmissionEvent"> <handler type="YourNamespace.ContactFormSubmissionHandler, YourAssembly" method="OnContactFormSubmission" /> </event> </events> <eventing> <events hint="list:RegisterEvent"> <event name="ContactFormSubmissionEvent"> <handler type="Sitecore.Eventing.EventHandler, Sitecore.Kernel" method="HandleEvent"> <param desc="eventName">ContactFormSubmissionEvent</param> </handler> </event> </events> </eventing> </sitecore> </configuration>
关键注意事项
- 确保CD与CM共享Core数据库(EventQueue存储在Core中)
- CD端配置
Eventing.Enabled=true - CM端应用池账户需拥有Master库写入权限和发布权限
- 提前在Master库创建提交数据存储文件夹和对应模板
内容的提问来源于stack exchange,提问作者Mohsin Khan
相关产品推荐
相关产品推荐

