You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:40:21