WFFM 170518 Tips & Tricks

Below you will find some tips and tricks that we found when implementing WFFM for Sitecore 8.2 Update 4.

Version: Web Forms for Marketers 8.2 rev. 170518

  1. You can’t mix Web Forms and the MVC Form rendering
    • 49048 16:14:46 ERROR Rendering control {F2CCA16D-7524-4E99-8EE0-78FF6394A3B3} not found for '/sitecore/content/Home'. Item id: {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}, database: master.
    • I hit this problem on a vanilla install of 8.2.4 with WFFM installed. If you try to add this form to the homepage item via the MVC form rendering provided expect this problem.
    • Cause: The sample layout provided for the default homepage uses a .aspx page.
    • Solution: You need to create a layout using MVC and assign to the page you want to add the MVC form rendering to.
  2. SIM (sitecore instance manager) hangs when install Sitecore 8.2.4 and Web Forms for Marketers 8.2 rev. 170518
    • Cause: We are not sure of the exact cause but installing this package with SIM results in the process crashing and burning.
    • Solution:  Install the Sitecore 8.2.4 with SIM and once up and running install the WFFM via the package manager in Sitecore instead.
  3. If your site does not have xDB available, you may want to use an SQL data store for your forms.
    • Not every site requires xDB to be turned on and the additional hosting and license cost may force your hand on this one.
    • If you want to revert back to the SQL database. Locate the DB files installed in the root of your website in the Data folder. Attach the DB’s to your SQL server.
      • The database should contain 2 x tables. WFFM SQL DB
    • Add the database connection string to the file connectionstring.config in the folder: App_Config
      • If your building with Helix create a transform file in your Foundation.Forms project.
      • foundationforms
      • <?xml version="1.0" encoding="utf-8"?>
        <connectionStrings xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
         <add name="wfm"
         connectionString="Data Source=WINDEV;Initial Catalog=Sitecore_Wffm;Integrated Security=False;User ID=sa;Password=itsasecret"
         xdt:Transform="Insert"/>
        </connectionStrings>

         

    • Create a patch config file to turn on sqlFormsDataProvider:
      <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
       <sitecore>
       <wffm>
       <analytics>
       <formsDataProvider patch:instead="*[@ref='/sitecore/wffm/analytics/analyticsFormsDataProvider']" ref="/sitecore/wffm/analytics/sqlFormsDataProvider"/>
       <sqlFormsDataProvider type="Sitecore.WFFM.Analytics.Providers.SqlFormsDataProvider, Sitecore.WFFM.Analytics">
       <param name="connectionStringName">wfm</param>
       </sqlFormsDataProvider>
       </analytics>
       </wffm>
       </sitecore>
      </configuration>

       

    • Not that when using the SQL Data Provider the tab “Detailed reports” will not work as it requires xDB
    • Image_2017-07-19_09.54.24_AM
  4. If your using the Send Mail Message action, located here: /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions/Send Email Message
    • Your going to want to overwrite the default mail server settings before deploying.
    • Create a patch config file for these settings
    • <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
       <sitecore>
       <settings>
       <setting name="MailServer" value="smtp.sendgrid.net" />
       <!-- MAIL SERVER USER
       If the SMTP server requires login, enter the user name in this setting
       -->
       <setting name="MailServerUserName" value="apikey" />
       <!-- MAIL SERVER PASSWORD
       If the SMTP server requires login, enter the password in this setting
       -->
       <setting name="MailServerPassword" value="SG.sdsdadXXCASFDa3423dfaXXXXXXXXXXXXXXXXXXXX" />
      
      <setting name="MailServerPort" value="25"/>
       </settings>
       </sitecore>
      </configuration>
    • This is handy in Helix setups.
    • If your using Azure why not take advantage of the Send Grid free tier. You can send a bunchof emails for free.
    • Also note that on the Send Email Message action you will need to set the host as well.
    • hostparameter

 

References:

Setting up Azure Search in Sitecore Helix

This applies to those setting up Azure Search to work with a Sitecore Helix architecture based on the Habitat example and using Sitecore 8.2 Update 3.

Depending on your use case Azure Search is a smart option if you’re hosting in the cloud. The main upside it likely has over SOLR is that its run as PaaS and you don’t need to delve into the SOLR setting files in order to enact scaling and replication. Nor does it require a true Virtual Machine running tomcat, that you may at times need to know how to administer. I’m not suggesting that SOLR isn’t a great project (it is) but it does have a learning curve if you need to tweak things under the hood. Azure Search also has its limitations as listed on this page.

If you’re following the setup instructions (like I was) there is a fairly lengthy step that involves you switching over configuration files. Basically, on a default installation, you need to disable/delete all Lucene file system based configuration files and enable a number of Azure configuration files for Azure Search PaaS.

Using Helix and gulp in Visual Studio all members of your team are probably going to need to replicate these setup steps (without doing anything manually in the running IIS developer instance).  So here are two tricks I used:

ConnectionStrings

Under your Foundation.Indexing module I placed a file called:

CaptureConnectionStrings

ConnectionString.config.transform

<?xml version="1.0" encoding="utf-8"?>

<connectionStrings xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
 <add name="cloud.search"
 connectionString="serviceUrl=https://mysearchinstance.search.windows.net;apiVersion=2015-02-28-Preview;apiKey=7CA4...5"
 xdt:Transform="Insert"/>
</connectionStrings>

 

Gulp Config Rename

In order to automate the deletion of all the Lucene config files I wrote the following Gulp task:

/*****************************
 https://doc.sitecore.net/sitecore_experience_platform/setting_up_and_maintaining/search_and_indexing/configure_azure_search#_Create_a_Search
 // If running on Azure Search we need to disable lucene default configs
*****************************/
gulp.task('Z-Search-Disable-Lucene-Configs', function () {

var root = config.websiteRoot + "/App_Config/Include/";
 var socialRoot = config.websiteRoot + "/App_Config/Include/social/";
 var listManagementRoot = config.websiteRoot + "/App_Config/Include/ListManagement/";
 var fxmRoot = config.websiteRoot + "/App_Config/Include/FXM/";
 var testingRoot = config.websiteRoot + "/App_Config/Include/ContentTesting/";

// Main root config folder
 var roots = [root + "Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config",
 root + "Sitecore.ContentSearch.Lucene.Index.Analytics.config",
 root + "Sitecore.ContentSearch.Lucene.Index.Core.config",
 root + "Sitecore.ContentSearch.Lucene.Index.Master.config",
 root + "Sitecore.ContentSearch.Lucene.Index.Web.config",

root + "Sitecore.Marketing.Lucene.Index.Master.config",
 root + "Sitecore.Marketing.Lucene.Index.Web.config",
 root + "Sitecore.Marketing.Lucene.IndexConfiguration.config",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Master.config",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Web.config",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.IndexConfiguration.config",

root + "Sitecore.Speak.ContentSearch.Lucene.config",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Web.config",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories. Lucene.IndexConfiguration.config",

root + "Sitecore.Speak.ContentSearch.Lucene.config",
 root + "Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.Xdb.config"
 
 ];




var fxmFiles = [
 fxmRoot + "Sitecore.FXM.Lucene.DomainsSearch.DefaultIndexConfiguration.config",
 fxmRoot + "Sitecore.FXM.Lucene.DomainsSearch.Index.Master.config",
 fxmRoot + "Sitecore.FXM.Lucene.DomainsSearch.Index.Web.config",
 ];




var listManFiles = [
 listManagementRoot + "Sitecore.ListManagement.Lucene.Index.List.config",
 listManagementRoot + "Sitecore.ListManagement.Lucene.IndexConfiguration.config",
 ];




var socialsFiles = [
 socialRoot + "Sitecore.Social.Lucene.Index.Master.config",
 socialRoot + "Sitecore.Social.Lucene.Index.Web.config",
 socialRoot + "Sitecore.Social.Lucene.IndexConfiguration.config",
 socialRoot + "Sitecore.Social.Lucene.Index.Analytics.Facebook.config"
 ];




var testingFiles = [
 testingRoot + "Sitecore.ContentTesting.Lucene.IndexConfiguration.config",
 ];

return Promise.all([
 new Promise(function (resolve, reject) {

gulp.src(roots).pipe(rename(function (path) {
 path.extname = ".config.disabled";
 })).pipe(gulp.dest(root));




gulp.src(fxmFiles).pipe(rename(function (path) {
 path.extname = ".config.disabled";
 })).pipe(gulp.dest(fxmRoot));

gulp.src(listManFiles)
 .pipe(rename(function (path) {
 path.extname = ".config.disabled";
 })).pipe(gulp.dest(listManagementRoot));

gulp.src(socialsFiles).pipe(rename(function (path) {
 path.extname = ".config.disabled";
 })).pipe(gulp.dest(socialRoot));

gulp.src(testingFiles).pipe(rename(function (path) { path.extname = ".config.disabled"; }))
 .pipe(gulp.dest(testingRoot));

}),
 new Promise(function (resolve, reject) {
 del(roots, { force: true });
 del(fxmFiles, { force: true });
 del(listManFiles, { force: true });
 del(socialsFiles, { force: true });
 del(testingFiles, { force: true });
 })
 ]).then(function () {
 // Other actions
 del(roots, { force: true });
 del(fxmFiles, { force: true });
 del(listManFiles, { force: true });
 del(socialsFiles, { force: true });
 del(testingFiles, { force: true });
 });
 
});

 

In order to automate the renaming of all the Azure config files I wrote the following Gulp task:

 

gulp.task('Z-Search-Enable-Azure-Configs', function () {

var root = config.websiteRoot + "/App_Config/Include/";
 var socialRoot = config.websiteRoot + "/App_Config/Include/social/";
 var listManagementRoot = config.websiteRoot + "/App_Config/Include/ListManagement/";
 var fxmRoot = config.websiteRoot + "/App_Config/Include/FXM/";
 var testingRoot = config.websiteRoot + "/App_Config/Include/ContentTesting/";

// Main root config folder
 var roots = [root + "Sitecore.ContentSearch.Azure.DefaultIndexConfiguration.config.disabled",
 root + "Sitecore.ContentSearch.Azure.Index.Analytics.config.disabled",
 root + "Sitecore.ContentSearch.Azure.Index.Core.config.disabled",
 root + "Sitecore.ContentSearch.Azure.Index.Master.config.disabled",
 root + "Sitecore.ContentSearch.Azure.Index.Web.config.disabled",

root + "Sitecore.Marketing.Azure.Index.Master.config.disabled",
 root + "Sitecore.Marketing.Azure.Index.Web.config.disabled",
 root + "Sitecore.Marketing.Azure.IndexConfiguration.config.disabled",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Master.config.disabled",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Web.config.disabled",
 root + "Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.IndexConfiguration.config.disabled"
 ];

gulp.src(roots) .pipe(rename(function (path) { path.extname = ""; path.basename = path.basename.replace(".disabled");
 })).pipe(gulp.dest(root));

// Testing files

var testingFiles = [
 testingRoot + "Sitecore.ContentTesting.Azure.IndexConfiguration.config.disabled",
 ];

gulp.src(testingFiles).pipe(rename(function (path) { path.extname = ""; path.basename = path.basename.replace(".disabled"); }))
 .pipe(gulp.dest(testingRoot));
 //del(testingFiles, { force: true });

// FXM files

var fxmFiles = [
 fxmRoot + "Sitecore.FXM.Azure.DomainsSearch.DefaultIndexConfiguration.config.disabled",
 fxmRoot + "Sitecore.FXM.Azure.DomainsSearch.Index.Master.config.disabled",
 fxmRoot + "Sitecore.FXM.Azure.DomainsSearch.Index.Web.config.disabled",
 ];

gulp.src(fxmFiles) .pipe(rename(function (path) { path.extname = ""; path.basename = path.basename.replace(".disabled");
 })).pipe(gulp.dest(fxmRoot));
 
 var listManFiles = [
 listManagementRoot + "Sitecore.ListManagement.Azure.Index.List.config.disabled",
 listManagementRoot + "Sitecore.ListManagement.Azure.IndexConfiguration.config.disabled",
 ];
 
 gulp.src(listManFiles)
 .pipe(rename(function (path) { path.extname = ""; path.basename = path.basename.replace(".disabled");
 })).pipe(gulp.dest(listManagementRoot));

var socialsFiles = [
 socialRoot + "Sitecore.Social.Azure.Index.Master.config.disabled",
 socialRoot + "Sitecore.Social.Azure.Index.Web.config.disabled",
 socialRoot + "Sitecore.Social.Azure.IndexConfiguration.config.disabled"
 ];

gulp.src(socialsFiles).pipe(rename(function (path) {
 path.extname = ""; path.basename = path.basename.replace(".disabled");
 })).pipe(gulp.dest(socialRoot));
});

 

I hope this saves you and your team some time when switching over to Azure Search on your Sitecore Helix project. Please leave us some comments if you have some more tips along these lines.

Azure FED Files missing in Helix

When deploying Sitecore to Azure if you come across an issue where your font files are marked as red in the chrome network tab (essentially they are not found), this may help.

Basically, you need to tell the web server to serve files with a particular extension.

In our case, the font files ending with the extension .woff were not getting picked up which results in a number of strange looking fonts around a deployed website.

The solution is to add this to your web.config:

<configuration>
    <system.webServer>
        <staticContent>
            <mimeMap fileExtension="woff" mimeType="application/font-woff" />
            <mimeMap fileExtension="woff2" mimeType="application/font-woff" /> 
         </staticContent>
    </system.webServer>
</configuration> 

This will tell the Azure web application to serve up files with the given extension as expected.

If you’re working with the Helix Architecture you might like to include this in your Foundation layer.

You could introduce it into a web.config.transform inside your Foundation assets project:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer xdt:Transform="InsertIfMissing">
      <staticContent xdt:Transform="InsertIfMissing">
          <mimeMap xdt:Transform="InsertIfMissing" xdt:Locator="Match(fileExtension)" fileExtension="woff" mimeType="application/font-woff" />
          <mimeMap xdt:Transform="InsertIfMissing" xdt:Locator="Match(fileExtension)" fileExtension="woff2" mimeType="application/font-woff" />
      </staticContent>
   </system.webServer>
</configuration>

Helix Development Settings and GIT

When you first start out working with the Helix architecture two files will standout as needing to be unique for each developer. Both of these file are part of the habitat example project that you can find here.

  • gulp-config.js (in the root of the project)
  • z.Website.DevSettings.config (\src\Project\Website\code\App_Config\Include\Project\)

These files contain directory locations that are probably going to be unique depending on how a team member sets up their projects.

The trick is that we want these files in git but we also don’t want the developer to check these files in again with there own settings each time.

The solution:

In the respective folders containing the files run the following git command in the cmd prompt:

git update-index --assume-unchanged

Your probably going to want to document this as one of the required setup steps after checking out the project from you git repository.


What if a developer ever needs to change this file and check it in again. They can reverse the process with:

git update-index --no-assume-unchanged