如何调试Sitecore Form ,尝试解决form 不能提交的问题 | How to debug sitecore form,try to resolve can't submit form issue.

背景

使用sitecore 10.1 作项目,因为有表单相关,所以就默认使用sitecore forms, 并安装了Sitecore Forms Extensions 这个插件
但是在使用过程遇到了一个问题,form不能成功提交数据,from做的是2个页面,提交成功后自动显示第二页的thank you信息,
(在Sitecore Experience Model下面却可以正常提交表单,并显示第二页Thank you信息。)
还有一点,在之前一个sitecore 9.3 sxa 的项目中同样的sitecore forms + sitecore forms extensions却可以正常提交

最初form提交总是会刷新页面,后来发现在是因为页面没有加载sitecore form 的一些js,在layout上引用如下即可:

@using Sitecore.ExperienceForms.Mvc.Html
@Html.RenderFormStyles()
@Html.RenderFormScripts()

https://doc.sitecore.com/developers/90/sitecore-experience-manager/en/add-a-form-to-a-webpage.html

尝试解决

根据上面的现象,最初是怀疑代码或者配置文件影响到了sitecore forms相关的代码,所以导致表单提交失败~
然后尝试去除所有业务代码和配置文件,发现还是同样的问题,没有解决~ , 同时也做了其它很多尝试但都 没有结果,

反编译sitecore.experienceforms , 并尝试复写相关代码,调试代码

note: sitecore forms 相关的配置文件名称为: App_Config\Sitecore\ExperienceForms\Sitecore.ExperienceForms.config

  1. 从Sitecore.ExperienceForms.Mvc.Controllers.FormBuilderController这个controller入手,Copy这个controller里面所有代码到项目中并创建自己的TestFormBuilderController, 不能使用相同的名称,因为sitecore代码在构造相关controller时会发现在同时controller,会有冲突
  2. 替换配置文件相关piplelines
      <!--register serviceType="Sitecore.ExperienceForms.Mvc.Controllers.FormBuilderController, Sitecore.ExperienceForms.Mvc" implementationType="Sitecore.ExperienceForms.Mvc.Controllers.FormBuilderController, Sitecore.ExperienceForms.Mvc" /-->
      <register serviceType="Test.Website.Controllers.TestFormBuilderController, Test.Website" implementationType="Test.Website.Controllers.TestFormBuilderController, Test.Website" />
  1. 修改Mvc Form rendering的Controller 为自己的,路径/sitecore/layout/Renderings/System/Forms/Mvc Form
    Controller字段修改为Test.Website.Controllers.TestFormBuilderController, Test.Website

  2. 修改formbuilder 路由 Sitecore.ExperienceForms.Mvc.Pipelines.Initialize.InitializeRoutes , Copy 全部代码并创建自己的InitializeRoutes
    "FormBuilder"路由名称不能修改, 路由修改为testformbuilder, controller也修改为自己创建的TestFormBuilder

        protected override void RegisterRoutes(RouteCollection routes, PipelineArgs args)
        {
            routes.MapRoute("FormBuilder", "testformbuilder/{action}/{id}", (object)new
            {
                controller = "TestFormBuilder",
                action = "Index",
                id = UrlParameter.Optional
            });
            routes.MapRoute("FieldTracking", "fieldtracking/{action}", (object)new
            {
                controller = "FieldTracking",
                action = "Register"
            });
        }
  1. 替换路由配置文件
        <!--processor type="Sitecore.ExperienceForms.Mvc.Pipelines.Initialize.InitializeRoutes, Sitecore.ExperienceForms.Mvc" /-->
        <processor type="Test.Website.Pipelines.InitializeRoutes, Test.Website" />

通过以上5个步骤应该提交form应该可以调试自己的TestFormBuilderController,代码了,但没有什么发现,问题依旧还在。。。

上面虽然可以调试了,但问题没有解决,不过不要灰心,通过可以调试部分代码了, 那么我就可以继续分析sitecore源代码,然后再可能会问题的代码都自己来实现并调试,一点一点的来分析到底是哪里出现了问题

我又做了很多测试,替换了Sitecore.ExperienceForms.Mvc.Processing.FormSubmitHandler ,
添加了SubmitError,

public class SubmitError : MvcPipelineProcessor<SubmitErrorEventArgs>
    {
        public override void Process(SubmitErrorEventArgs args)
        {
            Assert.IsNotNull(args.FormSubmitContext, nameof(args.FormSubmitContext));
            foreach(var error in args.FormSubmitContext.Errors)
            {
                NAE.Foundation.Logging.Log.Error("Form", error);
            }
        }
    }
      <forms.submitError>      
        <processor type="Test.Website.Pipelines.SubmitError, Test.Website" />
      </forms.submitError>

又添加了form.executeSubmit来记录日志

    public class TestActions : MvcPipelineProcessor<ExecuteSubmitActionsEventArgs>
    {
        public override void Process(ExecuteSubmitActionsEventArgs args)
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            Test.Foundation.Logging.Log.Info("Form", new { index = 1, args.FormSubmitContext });
        }
    }

      <forms.executeSubmit>
        <processor type="Test.Website.Processing.TestActions, Test.Website" />
        <processor type="Sitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.StoreFiles, Sitecore.ExperienceForms.Mvc" resolve="true" />
        <processor type="Test.Website.Processing.TestActions1, Test.Website" />
        <processor type="Sitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.GetSubmitActions, Sitecore.ExperienceForms.Mvc" />
        <processor type="Test.Website.Processing.TestActions2, Test.Website" />
        <processor type="Sitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.ExecuteActions, Sitecore.ExperienceForms.Mvc" />
        <processor type="Test.Website.Processing.TestActions3, Test.Website" />
      </forms.executeSubmit>

发现在日志都记录了,但表单还是没有提交成功,那。。。继续。。。
COPYSitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.ExecuteActions为自己的代码调试,发现args.SubmitActions数量为0?
好像快找到问题了,为什么submitactions 为0?没有action,当然不能成功提交数据了,那就上面的GetSubmitActions了,继续。。。

public override void Process(ExecuteSubmitActionsEventArgs args)
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            NAE.Foundation.Logging.Log.Info("Form", new { index = 3, args.FormSubmitContext });
            foreach (ParameterizedSubmitAction submitAction in args.SubmitActions)
            {
                if (args.FormSubmitContext.Canceled)
                    break;
                submitAction.SubmitAction.ExecuteAction(args.FormSubmitContext, submitAction.Parameters);
            }
        }

COPYSitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.GetSubmitActions代码出来调试,有时可得到args.SubmitActions, 有时得不到?

public virtual bool IsContactClassificationGuessed
        {
            get
            {
                return RobotDetectionHelper.IsContactClassificationGuessed;
            }
        }

        public override void Process(ExecuteSubmitActionsEventArgs args)
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            if (string.IsNullOrEmpty(args.FormSubmitContext.ButtonId))
                return;
            using (GetModelEventArgs args1 = new GetModelEventArgs())
            {
                args1.ItemId = args.FormSubmitContext.ButtonId;
                IViewModel viewModel = PipelineService.Get().RunPipeline<GetModelEventArgs, IViewModel>("forms.getModel", args1, (Func<GetModelEventArgs, IViewModel>)(a => a.ViewModel));
                args.SubmitActions = viewModel is ButtonViewModel buttonViewModel ? buttonViewModel.SubmitActions.Select(a => this.CreateAction(a, args.FormBuilderContext, args.FormSubmitContext)).Where(s => s != null).ToList() : null;
            }
        }

        protected virtual ParameterizedSubmitAction CreateAction(
          SubmitActionDefinitionData submitActionDefinitionData,
          IFormBuilderContext formBuilderContext,
          FormSubmitContext formSubmitContext)
        {
            return TestActions1.CreateSubmitAction(submitActionDefinitionData, formBuilderContext, formSubmitContext, this.IsContactClassificationGuessed);
        }

        private static ParameterizedSubmitAction CreateSubmitAction(
          SubmitActionDefinitionData submitActionDefinitionData,
          IFormBuilderContext formBuilderContext,
          FormSubmitContext formSubmitContext,
          bool isContactClassificationGuessed)
        {
            Item submitActionItem = formBuilderContext.Database.GetItem(submitActionDefinitionData.SubmitActionId, formBuilderContext.Language);
            if (submitActionItem != null)
            {
                SubmitActionData submitActionData = new SubmitActionData(submitActionItem);
                if (formSubmitContext.RobotDetectionEnabled && !submitActionData.RobotSubmissionEnabled && !isContactClassificationGuessed)
                    return (ParameterizedSubmitAction)null;
                if (InstanceHelper.CreateInstance(submitActionData.SubmitActionType, (object)submitActionData) is ISubmitAction instance)
                    return new ParameterizedSubmitAction()
                    {
                        SubmitAction = instance,
                        Parameters = submitActionDefinitionData.Parameters
                    };
            }
            return (ParameterizedSubmitAction)null;
        }

最后问题竟然和robot detection有关?意外了~
if (formSubmitContext.RobotDetectionEnabled && !submitActionData.RobotSubmissionEnabled && !isContactClassificationGuessed)
竟然竟然是认为我是机器人提交?所以没有保存数据~, 心中一万个~~~~~

继续看下去, 找到Sitecore.ExperienceForms.RobotDetection.RobotDetectionHelper

public static class RobotDetectionHelper
  {
    private const string AnalyticsGlobalCookieName = "SC_ANALYTICS_GLOBAL_COOKIE";

    public static bool IsContactClassificationGuessed
    {
      get
      {
        bool flag = false;
        HttpCookie cookie = HttpContext.Current?.Request.Cookies["SC_ANALYTICS_GLOBAL_COOKIE"];
        if (cookie != null && cookie.Value != null)
        {
          string[] strArray = cookie.Value.Split(new string[2]
          {
            "|",
            "%7c"
          }, StringSplitOptions.None);
          if (strArray.Length > 1)
            flag = bool.Parse(strArray[1]);
        }
        return flag;
      }
    }

    public static bool IsRobotDetectionAvailable
    {
      get
      {
        return Settings.GetBoolSetting("Xdb.Enabled", false) && Settings.GetBoolSetting("Xdb.Tracking.Enabled", false) && Settings.GetBoolSetting("Analytics.AutoDetectBots", false);
      }
    }
  }

和这个SC_ANALYTICS_GLOBAL_COOKIEcookie有关, 之前的项目之所以可以工作就是因为cookie为真,正在做的项目为假,
所以表单不能提交的问题大概找到了,就是这个cookie引起的, 接下来就是要看这个cookie是怎么创建的为什么值为假。

更新 2021-06-09

https://doc.sitecore.com/developers/91/sitecore-experience-platform/en/configure-robot-detection-functionality.html
最后找到在layout上面添加@Html.Sitecore().VisitorIdentification() 即可

总结

从上面可以看出,遇到一个问题无法下手时,慢慢靜下来,一点一点的分析,尝试去分析代码,尝试如果去调试相关代码,最后可能就发现问题的原因了~
此文记录问题找到过程,也希望可以帮助有相关问题的你~

评论

还没有人评论,抢个沙发吧...

Viagle Blog

欢迎来到我的个人博客网站