Getting settings from Sitecore config that aren’t in the settings section

Recently I had to write some code that got the value of the scheduling frequency in Sitecore config.  Normally, to get a value from Sitecore config, I’d simply use:


However, in this case, the value that I want is not in the <settings> node and the above code won’t work.  The value I want is in the <scheduling> node:

 <!-- SCHEDULING -->
 <!-- Time between checking for scheduled tasks waiting to execute -->

To get around this, instead, I used:


The above code should work for any Sitecore config item just by specifying the correct Xpath location for the value you require.

Sitecore Geo-Spatial Results with Azure Search

This is the second blog post in this series. In the first blog post, I spoke about setting up Azure Search.

In this post, I am going to talk about using a Geo-Spatial lookup query that Azure Search has built in and the associated Index data type called Edm.GeographyPoint

The Azure Search overview can be found here and the configuration document here.

If you’re simply looking for a working example jump over to our GitHub repository that contains the full working helix site.

You can also find the latest version of the Sitecore package here:

Notice on the configuration document that it has a list of EDM data types and it also references the document from Microsoft which has the same list.

A notable exception is the that EDM.GeographyPoint is mentioned in the Microsoft document but not the Sitecore EDM list. So if you need to implement a geo-spatial lookup and get back results based on a latitude and longitude that isn’t possible with the Sitecore Azure Search provider out of the box.

If you dig a little deeper you can see that EDM.GeographyPoint is not in the search code. Have a look at the source code in Sitecore.ContentSearch.Azure.Schema.dll CloudSearchTypeMapper.GetNativeType()

We asked Sitecore support when and if EDM.GeographyPoint would be supported by the Sitecore provider and the answer was no plans in the immediate future.

The solution we came up with to solve this problem essentially involved two steps:

  • Getting data of type EDM.GeographyPoint into the Azure Search Index.
  • Performing a Spatial Query on the Azure Search Index (using geo.distance) in a timely manner.

To support both of the above operations we had to do a little digging into the core Sitecore Azure search code. Read on to find out about the solution we came up with or jump on over to the GitHub repository to look over the code.

Getting data into the index

As noted above the EDM.GeographyPoint data type simply isn’t coded into the Sitecore DLLs.  You can see this by looking at CloudSearchTypeMapper.GetNativeType() inside the DLL Sitecore.ContentSearch.Azure.Schema.dll.

If you’re still not convinced have a look in the Sitecore.ContentSearch.Azure.Http.dll


The next thing we tried was adding Edm.GeographyPoint as a field converter.

Once again we hit a brick wall with this solution as that doesn’t change the fact that Edm.GeographyPoint is not actually a known cloud type in the core DLLs.

If you look at the error message you get when attempting to add Edm.GeographyPoint as a Converter it tells us that CloudIndexFieldStorageValueFormatter.cs is attempting to look up the native EDM type.

Exception: System.NotSupportedException
Message: Not supported type: ‘Edm.GeographyPoint’
Source: Sitecore.ContentSearch.Azure at Sitecore.ContentSearch.Azure.Schema.CloudSearchTypeMapper.GetNativeType(String edmTypeName) at Sitecore.ContentSearch.Azure.Converters.CloudIndexFieldStorageValueFormatter.FormatValueForIndexStorage(Object value, String fieldName) at Sitecore.ContentSearch.Azure.CloudSearchDocumentBuilder.AddField(String fieldName, Object fieldValue, Boolean append)

Working around this limitation took a bit of trial and error but eventually, we nailed it down to the following steps:

  1. Created a new search configuration called spatialAzureIndexConfiguration.
  2. Create a new index configuration based on the new configuration in step 1.
  3. In the search configuration from step 1.
    • Add the following computed field.
    • <fields hint="raw:AddComputedIndexField">
       <field fieldName="geo_location" type="Aceik.Foundation.CloudSpatialSearch.IndexWrite.Computed.GeoLocationField, Aceik.Foundation.CloudSpatialSearch" />
    • Add a new cloud type mapper to map to EDM.GeographyPoint
    • <cloudTypeMapper ref="contentSearch/indexConfigurations/defaultCloudIndexConfiguration/cloudTypeMapper">
       <maps hint="raw:AddMap">
       <map type="Aceik.Foundation.CloudSpatialSearch.Models.GeoJson, Aceik.Foundation.CloudSpatialSearch" cloudType="Edm.GeographyPoint"/>
    • Replace the standard index field storage value formatter with the following the following class.
    • <indexFieldStorageValueFormatter type="Aceik.Foundation.CloudSpatialSearch.IndexWrite.Formatter.GeoCloudIndexFieldStorageValueFormatter, Aceik.Foundation.CloudSpatialSearch">
       <converters hint="raw:AddConverter">
  4. Our new formatter GeoCloudIndexFieldStorageValueFormatter.cs  inherits from the formatter in the core dlls and overrides the method FormatValueForIndexStorage. It detects if the field name contains “_geo” and basically prevents CloudSearchTypeMapper.GetNativeType from ever running and falling over.


The computed field GeoLocationField returns a GeoJson POCO which is serialised to the GeoJson format ( which is required for storage in Azure Search Index.

Getting data out of the index

The GitHub solution demonstrates two solutions.

Both solutions above at the end of the day allow you to perform an OData Expression query against your Azure Search Indexes. Using the “geo.distance” filter allows us to perform spatial queries using the computing power of the cloud.

The only downside is that search results returned don’t actually include the distance as a value. They are correctly filtered and ordered by the distance yet the actual distance value itself is not returned. We suggest voting for this change on this ticket :). For now, we suggest using the System.Device.Location.GeoCoordinate to figure out the distance between two coordinates.


In researching for possible solutions already out there we had a look at the following implementations for Lucene and SOLR:

  1. Sitecore Solr Spatial:
  2. Sitecore Lucene Spatial:

Special Thanks:

  • Ed Khoze –  For the research, he did and help with the initial prototype. Plus google address lookup advice.
  • Jose Dominguez – For getting the OData filtering query working.


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="">
         <add name="wfm"
         connectionString="Data Source=WINDEV;Initial Catalog=Sitecore_Wffm;Integrated Security=False;User ID=sa;Password=itsasecret"


    • Create a patch config file to turn on sqlFormsDataProvider:
      <configuration xmlns:patch="">
       <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>


    • 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="">
       <setting name="MailServer" value="" />
       <!-- MAIL SERVER USER
       If the SMTP server requires login, enter the user name in this setting
       <setting name="MailServerUserName" value="apikey" />
       If the SMTP server requires login, enter the password in this setting
       <setting name="MailServerPassword" value="SG.sdsdadXXCASFDa3423dfaXXXXXXXXXXXXXXXXXXXX" />
      <setting name="MailServerPort" value="25"/>
    • 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



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:


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



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

<connectionStrings xmlns:xdt="">
 <add name=""


Gulp Config Rename

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

 // 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";

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

 .pipe(rename(function (path) {
 path.extname = ".config.disabled";

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

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

 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");

// 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"); }))
 //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");
 var listManFiles = [
 listManagementRoot + "Sitecore.ListManagement.Azure.Index.List.config.disabled",
 listManagementRoot + "Sitecore.ListManagement.Azure.IndexConfiguration.config.disabled",
 .pipe(rename(function (path) { path.extname = ""; path.basename = path.basename.replace(".disabled");

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");


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:

            <mimeMap fileExtension="woff" mimeType="application/font-woff" />
            <mimeMap fileExtension="woff2" mimeType="application/font-woff" /> 

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="">
  <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" />

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

Aceik’s Jason Horne Wins Sitecore “Most Valuable Professional” Award 2017

Elite distinction awarded for exceptional contributions to the Sitecore community sitecore_mvp_logo_technology_2017

Melbourne, Victoria, Australia — January 31, 2017, Aceik today announced that Jason Horne has been named a “Most Valuable Professional (MVP)” by Sitecore®, the global leader in experience management software. Jason Horne was one of only 215 Technologist worldwide to be named a Sitecore MVP this year.

Now in its eleventh year, Sitecore’s MVP program recognises individual technology, digital strategy, commerce, and cloud advocates who share their Sitecore passion and expertise to offer positive customer experiences that drive business results. The Sitecore MVP Award recognises the most active Sitecore experts from around the world who participate in online and offline communities to share their knowledge with other Sitecore partners and customers.

Aceik provides a complete range of Sitecore services; architecture, development, integration, support and maintenance, intranets, expert help, existing site audits and upgrades. As Sitecore specialists, Aceik strives to provide excellence in every Sitecore project we undertake.

Aceik contributes to the Sitecore community through thought leadership content on our blog, the Sitecore community blog and stack overflow. We co-founded the Melbourne Sitecore user group, founded the Sitecore ANZ certified developers group and continue to be involved in their ongoing management with the goal to share knowledge, learn and build the Sitecore community within Australia and New Zealand.

“The Sitecore MVP awards recognise and honour those who make substantial contributions to our loyal community of partners and customers,” said Pieter Brinkman, Director of Developer and Platform Evangelism, Sitecore. “MVPs consistently set a standard of excellence by delivering technical chops, enthusiasm and a commitment to giving back to the Sitecore community. They truly understand and deliver on the power of the Sitecore Experience Platform to create contextualised brand experiences for their consumers, driving revenue and loyalty for life.”

Sitecore’s experience platform combines web content management, omnichannel digital delivery, customer insight and engagement, and strategic digital marketing tools into a single, unified platform. The platform is incredibly easy to use, capturing every minute interaction—and intention—that customers and prospects have with a brand, both on a website and across other online and offline channels. The end-to-end experience technology works behind the scenes to deliver context marketing to individual customers so that they engage in relevant brand experiences that earn loyalty and achieve business results.

Aceik is a boutique web development company specialising in the technical implementation and support of Sitecore solutions. 100% of our work is Sitecore related and we pride ourselves on being experts in our field.

Jason Horne, Founder and Sitecore specialist

More information can be found about the MVP Program on the Sitecore MVP site:

Advanced System Reporter Custom Reports Part 4

Custom Viewer Report

For this example, we will build a report which displays a set of results based on a Sitecore Query with a custom viewer to display additional fields from your custom solution.


The report will display all items under the content path selected by the user. The report must also display the “Title” field in the report results in addition to the standard fields.

Let’s build it

Step 1: Open up the ASR source code project in Visual Studio. Find the ItemViewer class, then copy it to your solution in an appropriate library. You will need to reference the ASR and ASR.Reports DLLs.

Rename the viewer to “CustomItemViewer” for the purposes of this example.

Now we can add our custom field to the view by editing the “getColumnText” and “AvailableColumns” methods.



Step 2: Create a viewer item called “Custom Item Viewer” and configure as per the image. In the Viewer field click edit and add the new Title field to the list in the order you wish to display it in your report.


Step 3: Create a report item called “Custom Item Viewer Report” and configure as per the image.


Step 4: Run the ASR report and find your custom field displayed in the report results in the order you defined in the viewer.


Advanced System Reporter Custom Reports Part 3

Simple Custom Parameters Report

For this example, we will build a report which displays a set of results based on a Sitecore Query and custom parameters.


The report will display all items under a path selected by the user in the content tree and only return items of a template selected by the user.

Let’s build it

Step 1: Create a new filter called “Items of Type” and configure as per the image.


Step 2: Create a Parameter item called “TemplateID” and configure as per the image.


Note that the root id refers to the root templates folder you wish the user to be able to filter from.

Step 3: Create a report item called “Items by Template” and configure as per the image.


Step 4: Run the report from ASR. Here you can see we have run the report to return all articles within the categories node of the content tree.


Advanced System Reporter Custom Reports Part 2

Simple Sitecore Query based Report

For this example, we will build a report which displays a set of results based on a Sitecore Query.


The report will display all items under a fixed path in the content tree and only return items of predefined specific templates. The report query is fixed and doesn’t require any user input via report parameters.

Let’s build it

Step 1: Create a scanner called “Simple Sitecore Query” and add a query as per the image. The query below gets all items under the categories node where the template is one of the three listed types of templates.


Step 2: Create a new report called “Simple Sitecore Query Report” and configure as per the image.


Step 3: Run the report from ASR. Here you can see we have run the report to return all items of the specific templates within the categories node of the content tree.