Dependency Injection with WFFM

There were a number of changes in the 8.1 release of the Web Forms For Marketers module, it was a fairly significant rewrite but not unusual given the introduction of a number of abstractions within the core product itself. In hindsight, all this was just setting the stage for the introduction of Dependency Injection in Sitecore 8.2.

One of the big changes in WFFM now allows us to inject dependencies into Save Actions using configuration. I’ve not seen this blogged previously and the documentation is a little sparse on this subject so thought it is worth reviewing since it has also come up on StackExchange before.

Previous way of defining Save Actions

Previously in WFFM you defined Save Actions as items in Sitecore under /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions and set the Assembly + Class fields to point to the code definition.

WFFM Save Action

WFFM Save Action

Inject Dependencies

Since the changes in WFFM 8.1+ these fields are now empty and instead a new field is populated, the Factory Object Name. The following is defined for the Send Email Message Save Action:

WFFM Save Action with Dependency Injections

WFFM Save Action with Dependency Injections

The path actually points to a Sitecore configuration node, defined in /App_Config/Include/Sitecore.WFFM.Dependencies.config:

<sitecore>
  <wffm>

    <settings type="Sitecore.Forms.Core.Dependencies.DefaultImplSettings, Sitecore.Forms.Core">
      <param name="sitecoreContextWrapper" ref="/sitecore/wffm/sitecoreContextWrapper" />
    </settings>
    <mailSender type="Sitecore.Forms.Core.Dependencies.DefaultImplMailSender, Sitecore.Forms.Core">
      <param name="itemRepository" ref="/sitecore/wffm/itemRepository" />
    </mailSender>
    <sitecoreContextWrapper type="Sitecore.Forms.Core.Wrappers.SitecoreContextWrapper, Sitecore.Forms.Core"/>
    <itemRepository type="Sitecore.Forms.Core.Dependencies.DefaultImplItemRepository, Sitecore.Forms.Core"/>

    <!--Save actions constructor configuration-->
    <actions>
      <sendMessage type="Sitecore.WFFM.Actions.SaveActions.SendMessage, Sitecore.WFFM.Actions">
        <param name="settings" ref="/sitecore/wffm/settings" />
        <param name="mailSender" ref="/sitecore/wffm/mailSender" />
      </sendMessage>
    </actions>

  </wffm>
</sitecore>

The above is a stripped down version of the config, but you can see that the sendMessage path matches that which is defined in the Save Action item. The node is defined using Sitecore Configuration Factory, and two additional parameters passed to the Constructor. The params in this instance are defined as ref attributes which in turn point to other objects defined in the config file.

public class SendMessage : WffmSaveAction, IEmailAttributes
{
  private readonly IMailSender mailSender;
  private readonly IEmailAttributes emailAttributes;

  public SendMessage(ISettings settings, IMailSender mailSender)
  {
    this.mailSender = mailSender;
    this.emailAttributes = (IEmailAttributes) new EmailAttributes(settings.EmailFromAddress, settings.MailServer, settings.MailServerUserName, settings.MailServerPassword, settings.MailServerPort);
  }
  ...
  public override void Execute(ID formId, AdaptedResultList adaptedFields, ActionCallContext actionCallContext = null, params object[] data)
  {
    this.mailSender.SendMail(this.emailAttributes, formId, adaptedFields, data);
  }
}

The params defined in config must match the parameters of your Constructor – both the name and the type. It will be will all be wired up automatically by the module as you would expect using any DI framework.

Need to pass in additional parameters? Add an additional entry in config and update the constructor to match. Need to switch out the entire implementation for something else? No problem, you can patch in a different implementation. No more updating or duplicating default item definitions.

You can continue to use the old method of defining Save Actions, the do not need to be configuration driven, which is nice for backwards compatibility but you should define them in configuration going forward.

Yo dawg

Links

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s