bartverdonck / Sitecore-Forms-Extensions

http://onelittlespark.bartverdonck.be/category/sitecore-forms-extensions/
MIT License
59 stars 37 forks source link

Subscribe to List Submit action not working #124

Open SchelstraeteRuben opened 3 years ago

SchelstraeteRuben commented 3 years ago

Hi,

We noticed that the Subscribe to list action doesn't work every time. It seems that it doesn't work on CD and I believe I found why. This might be high priority as it renders one of the key features unusable.

The following error is thrown upon form submission:

Exception: System.NullReferenceException Message: Object reference not set to an instance of an object. Source: Feature.FormsExtensions at Feature.FormsExtensions.SubmitActions.SubscribeToList.SubscribeToListAction.Execute(SubscribeToListData data, FormSubmitContext formSubmitContext) at Sitecore.ExperienceForms.Processing.Actions.SubmitActionBase1.ExecuteAction(FormSubmitContext formSubmitContext, String parameters) at Sitecore.ExperienceForms.Mvc.Pipelines.ExecuteSubmit.ExecuteActions.Process(ExecuteSubmitActionsEventArgs args) at (Object , Object ) at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs](String pipelineName, TArgs args) at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs,TResult](String pipelineName, TArgs args, Func2 resultGetter) at Sitecore.ExperienceForms.Mvc.Processing.FormSubmitHandler.ExecuteSubmitActions(FormSubmitContext submitContext) at Sitecore.ExperienceForms.Mvc.Processing.FormSubmitHandler.Submit(FormSubmitContext submitContext) at Sitecore.ExperienceForms.Mvc.Controllers.BaseFormBuilderController.ProcessFormData(FormDataModel data) at Sitecore.ExperienceForms.Mvc.Controllers.FormBuilderController.Index(FormDataModel data) at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass24_0.<InvokeActionMethodWithFilters>b__0() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

It looks like the nullref exception is thrown in Feature.FormsExtensions.SubmitActions.SubscribeToList, line 56 (SubscriptionService.Subscribe().

There is a Sitecore.ListManagement.Services.config file which inserts a CustomServiceConfigurator:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/"
               xmlns:role="http://www.sitecore.net/xmlconfig/role/">
  <sitecore role:require="Standalone or ContentManagement">
    <!-- SITECORE SERVICES WEB API FILTERS 
         Specifies the list of Web API filters to load for request handling
    -->
    <api>
      <services>
        <configuration>
          <allowedControllers hint="list:AddController">
            <allowedController desc="ActionsController">Sitecore.ListManagement.Services.ActionsController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="ContactListController">Sitecore.ListManagement.Services.ContactListController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="ContactsController">Sitecore.ListManagement.Services.Controllers.ContactsController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="ExportController">Sitecore.ListManagement.Services.Controllers.ExportController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="ImportController">Sitecore.ListManagement.Services.ImportController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="SecurityController">Sitecore.ListManagement.Services.SecurityController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="SegmentController">Sitecore.ListManagement.Services.Controllers.SegmentController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="ListController">Sitecore.ListManagement.Services.Controllers.ListController, Sitecore.ListManagement.Services</allowedController>
            <allowedController desc="SegmentedListController">Sitecore.ListManagement.Services.Controllers.SegmentedListController, Sitecore.ListManagement.Services</allowedController>
          </allowedControllers>
        </configuration>
      </services>
    </api>
    <services>
      <configurator
        type="Sitecore.ListManagement.DependencyInjection.CustomServiceConfigurator, Sitecore.ListManagement" />
      <configurator
        type="Sitecore.ListManagement.XConnect.Web.DependencyInjection.CustomServiceConfigurator, Sitecore.ListManagement.XConnect.Web" />
      <configurator
        type="Sitecore.ListManagement.Services.DependencyInjection.CustomServiceConfigurator, Sitecore.ListManagement.Services" />
    </services>
  </sitecore>
</configuration>
internal class CustomServiceConfigurator : IServicesConfigurator
  {
    public void Configure(IServiceCollection serviceCollection)
    {
      serviceCollection.AddTransient<ISubscriptionService, SubscriptionService>();
      serviceCollection.AddTransient<IXdbClientFactory, XdbClientFactory>();
      serviceCollection.AddTransient<IContactDataReaderFactory, ConfigurationContactDataReaderFactory>();
      serviceCollection.AddTransient<IContactProvider, ContactProvider>();
      serviceCollection.AddTransient<ISegmentationService, SegmentationService>();
      serviceCollection.AddTransient<IContactSourceFactory, ContactSourceFactory>();
      serviceCollection.AddTransient<ContactSubscriptionChangeHandler>();
      serviceCollection.AddTransient<IContactSourceProvider, ContactSourceProvider>();
      serviceCollection.AddTransient<IListCombiner<Contact>, ListCombiner>();
      serviceCollection.AddTransient<IBatchedListCombiner, ListCombiner>();
      serviceCollection.AddTransient<IContactSourceBasedListCombiner, ListCombiner>();
      serviceCollection.AddTransient<ISubscriptionSourceService, SubscriptionSourceService>();
      serviceCollection.Decorate<IDefinitionManager<IContactListDefinition>, Sitecore.ListManagement.XConnect.Web.ContactListDefinitionManager>();
    }
  }

This CustomServiceConfigurator is responsible for registering the SubscriptionService. But as you can see this config is only inserted on Standalone & ContentManagement roles, and not on ContentDelivery roles. This causes the nullreference when trying to use the Subscribe To List Action on CD.

Possible fixes:

Afaik this is applicable for all supported Sitecore versions, so all packages might need to be updated.

markgibbons25 commented 3 years ago

Please see #120 . You didnt mention what version you are on but latest has that config enabled on CD.

roberutokdo commented 2 years ago

I'd like to watch this thread since I'm having kind of the same issue. I created a form with only 3 fields (name, last name, and email), added the "Subscript to List" action, and when the form is submitted, the contact is not properly saved in the Contact List:

image

Sitecore 10.1 - standard (no CM/CD) SFE 4.0.2