Using xProfile Data to Populate a WFFM - Part 3: Rule Macro for Facet Selection

Tuesday, March 01, 2016 @ 04:30

By: Scott Gillis, Lead Consultant – At the start of the series, I thought this was going to be the easiest element of the solution. I figured I could just decompile the provided Web Forms for Marketers (WFFM) save action that updates a contact record. Turns out, this was a helpful starting point and that's it!

The second element when writing the text for a new rule or action is used to identify a marco. Macros provide a level of interaction to the user in further refining what should occur.

For our custom WFFM action, we want to provide the editor the ability to select a specific member from the list of available contact facets, instead of manually entering a value that we must program for, and assume our editor won't mistype a key.

Creating a macro consists of three items:

  • Sitecore Artifact
  • IRuleMacro Implementation in Compiled Code
  • Sheer XAML Screen

Sitecore Artifact

We'll ease into the creation process by first setting up our Sitecore Artifact:

  1. Login and open the Content Editor
  2. Expand the content tree to the Macros (sitecore \ system \ settings \ Rules \ Definitions \ Macros)
    Image One - Sitecore Tree
  3. Right-click on Macros, select Insert and choose Macro. (If your plans involve creating multiple macros, you may want to generate a folder via the 'Insert from Template' option.)
    1. When prompted for a name, give a name that does NOT include spaces or special characters
    Image Two - Sitecore Tree Click Options
  4. In the new Macro item, you will need to complete the Type field. In this, you will enter Namespace.Class, Assembly of the IRuleMacro implementation. (In my testing, there appears to be not system difference between including a space after the comma or excluding a space)
    Image Three - Sitecore Backend
  5. Save the item

IRuleMacro Implementation

All rule macros are an implementation of Sitecore.Rules.RuleMacros.IRuleMacro (found in Sitecore.Kernel). There is a single method to implement named Execute, its signature looks like the following:

/// <name="element">XML of calling condition rule or action</param>
/// <param name="name">property of the condition/action that will be set by the macro</param>
/// <param name="parameters">parameter details, the third comma in the text</param>
/// <param name="value">currently set value to the property</param>
public void Execute(XElement element, string name, UrlString parameters, string value)

This method is what is called when a user clicks the underlined text in an action or rule where the marco has been defined.

The Execute method is what calls the specific Sheer screen that the user will interact with.

The Sheer screen is launched via a call to SheerResponse.ShowModalDialog, which you pass a URL string object pointing to the sheer screen that is to be shown. So my simple Execute implementation to launch a custom screen would be:

One of the keys to making the Sheer screen function properly is the passing of all data required, such as current values, to the screen via query string parameters. In addition, the URL used is not the file path to the your XAML screen. You pass just the name with the sudo-path of '/sitecore/shell/~/xaml' and a custom Sitecore handler will perform a lookup and find the correct screen to show.

It is more common that you may want to just run some custom logic before a pre-built screen is shown. In such a case, you can easily decompile an existing implementation to copy from.

Sheer XAML Screen

Having not worked with Sheer modals before, I found this to be the most difficult part of the process. There is a lot of documentation around making application type screens with Sheer, but not much around the use of them in IRuleMacro implementations, so I'll cover some of the key points I ran into as I built my screen.

As a refresher, my end goal was to allow the editor the ability to select from a list of contact facet members, instead of hard coding a switch expecting only a limited number of facet options, so our finished product should be:

Image Four - Sitecore Selection Modal
  • The first issue I came across was that the use of the commonly documented 'CodeBeside' file did not properly trigger any of my custom code required to retrieve facets or save a selection. Instead, I had to use the attribute
    1. x:inherits="TheCodeAttic.SharedSource.WFFM.PopulateFieldAction.Sheer.ConatactFacetDialog,
      TheCodeAttic.SharedSource.WFFM.PopulateFieldAction"
  • Through this same testing, I found that for some of the suggested Sheer dialog nodes, the expected triggering only occurred when using:
    <Sitecore.Controls.DialogPage runat="server">
  • The custom handler Sitecore uses to render Sheer XAML automatically looks with in the 'sitecore modules \ Shell' directory of the web root. Best practices would have you create a custom folder here to store your Sheer XAML in

With these two items in mind, our basic shell is:

Now, a quick switch over to the code behind that supports our screen. This is where the magic happens!

  • Deviating again from most samples, I found that the most success was occurring when my class inherits from Sitecore.Controls.DialogPage, found in Sitecore.Client.dll
  • Key methods that you will want to override are
    • protected override void OnInit(EventArgs e)
      • Perform initialization and most importantly loads values from the query string parameter that controls/supports your screen
    • protected override void OnLoad(EventArgs e)
      • Just as with standard ASPX web forms, this would be were or load logic goes
      • Click events occur as post backs to this file, so you must code defensively against any button clicks by wrapping your initial load code in
        if (!Page.IsPostBack)
    • protected override void OK_Click( )
      • Method that is pre-wired to the OK button
    • protected override void Cancel_Click( )
      • Method that is pre-wired to trigger when the Cancel button is clicked
  • To make sure the value(s) that the editor is entering or selecting to be made available to the action or condition, the following code needs to be used
    • XamlControl.AjaxScriptManager.SetDialogValue(value); where "value" has been entered/selected by the user

And that's the basics to creating a rule macro and it's corresponding screen to capture more controlled information from your editors.

Check-out the full source solution on GitHub. Until commenting gets implemented, feel free to tweet me questions or comments @thecodeattic or on Sitecore Slack Community as @gillissm.

Entire Series

Post One – Auto-Populate a WFFM Field
Post Two – Read from Contact Facet Action
Post Three – Rule Macro for Facet Selection
Post Four – Smart Form

 

 

Scott Gillis, Lead Consultant at Paragon and 2017 Sitecore MVP, has been working with Sitecore for several years. He has a deep passion for helping clients leverage their content and data into powerful new capabilities in Sitecore and has produced successful outcomes as the technical lead on numerous, complex implementations. Recently, Scott has been focusing on helping these clients take advantage of the wealth of data collected by Sitecore Experience Analytics.