Solr docker container for Sitecore 8.2

04/10/2016 Leave a comment

For some time, I’ve wanted to work with Docker. So I took on the task of creating a Solr container for Sitecore, a container you can turn on and have all the required Solr Cores configured and preinstalled, so it just works with Sitecore. This post is not a detailed introduction to Docker if you want a detailed introduction I suggest looking at their website This post is only meant to be a simple demo to shown how you could combine Docker with Sitecore. Dont use this container for more than testing, it is not suposed to be used in production.

First I found a  suitable  Docker container image to start from , my choice : the Solr:5.3 found here :

I’ve installed the images “spun up a docker container” pulled  the schema file and ran it through Sitecore 8.2 “enrichment” process. Next I started to build my docker file containing all the configuration for building the container ie configuring the different cores . All that happens is  first to copy in the new schema file  to the basic_configset and afterwards copy the basic_configset to multiple new folders one for each core. See the docker file below

FROM solr:5.3


ENV SOLR_PATH /opt/solr/server/solr

COPY resources/schema.xml $SOLR_PATH/configsets/basic_configs/conf

RUN cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_core_index && \
echo name=sitecore_core_index > $SOLR_PATH/sitecore_core_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_master_index && \
echo name=sitecore_master_index > $SOLR_PATH/sitecore_master_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_web_index && \
echo name=sitecore_web_index > $SOLR_PATH/sitecore_web_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_fxm_master_index && \
echo name=sitecore_fxm_master_index > $SOLR_PATH/sitecore_fxm_master_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_fxm_web_index && \
echo name=sitecore_fxm_web_index > $SOLR_PATH/sitecore_fxm_web_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_list_index && \
echo name=sitecore_list_index > $SOLR_PATH/sitecore_list_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketing_asset_index_master && \
echo name=sitecore_marketing_asset_index_master > $SOLR_PATH/sitecore_marketing_asset_index_master/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketing_asset_index_web && \
echo name=sitecore_marketing_asset_index_web > $SOLR_PATH/sitecore_marketing_asset_index_web/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketingdefinitions_master && \
echo name=sitecore_marketingdefinitions_master> $SOLR_PATH//sitecore_marketingdefinitions_master/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketingdefinitions_web && \
echo name=sitecore_marketingdefinitions_web > $SOLR_PATH/sitecore_marketingdefinitions_web/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_suggested_test_index && \
echo name=sitecore_suggested_test_index > $SOLR_PATH/sitecore_suggested_test_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_testing_index && \
echo name=sitecore_testing_index > $SOLR_PATH/sitecore_testing_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/social_messages_master && \
echo name=social_messages_master > $SOLR_PATH/social_messages_master/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/social_messages_web && \
echo name=social_messages_web > $SOLR_PATH/social_messages_web/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_analytics_index && \
echo name=sitecore_analytics_index > $SOLR_PATH/sitecore_analytics_index/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_core_indexMainAlias && \
echo name=sitecore_core_indexMainAlias > $SOLR_PATH/sitecore_core_indexMainAlias/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_master_indexMainAlias && \
echo name=sitecore_master_indexMainAlias > $SOLR_PATH/sitecore_master_indexMainAlias/ && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_web_indexMainAlias && \
echo name=sitecore_web_indexMainAlias > $SOLR_PATH/sitecore_web_indexMainAlias/

You can see the project here at github  the container image is at dockerhub  at

You can test it out  by installing docker and then running the following command.

docker run –name nameofyoucontainer -d -p 8983:8983 istern/solr-sitecore:8.2

You can now reach you solr admin interface on your http://localhost:8983

If you want to add an extra core I’ve made a script you can run from your favorite prompt.

 docker exec [NAMEOFYOURSOLRCONTAINER] ./ NameOfNewCore

You could combine the above image with docker compose to have both a solr and mongo running in containers. Below is an example  of a docker-compose.yml

version: ‘2.0’
image: istern/solr-sitecore:8.2
– “8983:8983”
image: mongo
– “27020:27017”

you can test it by runnning the following command . The “-d” means as a daemon in he background.

docker-compose up -d

and now you have both a solr and mongo server running as  containers .

A big thanks to @pbering for getting me started and helping m with all my silly docker questions.

Categories: Docker, Sitecore 8 Tags: ,

Unit testing in Sitecore 8.2

19/09/2016 Leave a comment

Sitecore has done a great job but abstracting a lot and marking a lot of methods as Virtual, take the Datbase class for instance it is now abstract class, and implement in the DefaultDatabase Also all methods in the Item class is now marked virtual. I must say I think It is great way Sitcore is heading, and they are doing great but allowing developers easly testing the code by taking the framework in this direction.

Ok,  but before I could also test using Microsoft Fakes, yes and there is Sitecore FakeDB, and also there was the old Framework I created myself Sitecore.Fakes, which didn’t work with sitecore 7+ because the Database contructer was made internal,  but now working again in 8.2, the latter two Framworks (Sitecore FAkeDB and Sitecore.Fakes) required additional setup in a App.config along with a license file in your Test project  With the changes mention before this is no longer required ..  I’ve updated the Sitecore.Fakes found here the solution contains examples of how to test with this Framework, a simple example is given below.


public void NewFakeItemDefaultNameShouldBeFakeItem()


var fake = new FakeItem();



Note I’ve trimmed the framework a lot, ie. removed functionality that will be rewritten., so it is no longer as feature rich as before but now working J, also it is by fare not as feature rich as Sitecore FakeDB.

Running Sitecore Field Editor from a Speak Command in Sitecore Experience editor Sitecore 8.1 Version

14/12/2015 Leave a comment

So with the release of sitecore 8.1 also came some minor changes to how the javascript are structured, this means that to run the Sitecore Field Editor from a Speak Command in Sitecore Experience editor, which i presented in this post, a minor changes is required. All that is needed to be changed is the way the reference to Experience editor is handled the full Javascript with the modification is show below.

define(["sitecore", "/-/speak/v1/ExperienceEditor/ExperienceEditor.js"], function (Sitecore, ExperienceEditor) {
    Sitecore.Commands.LaunchFieldEditor =
        canExecute: function (context) {
            return true;
        execute: function (context) {
            context.currentContext.argument = context.button.viewModel.$el[0].firstChild.alt;

            context.currentContext.argument = context.button.viewModel.$el[0].title;
            ExperienceEditor.PipelinesUtil.generateRequestProcessor("ExperienceEditor.GenerateFieldEditorUrl", function (response) {
                var DialogUrl = response.responseValue.value;
                var dialogFeatures = "dialogHeight: 680px;dialogWidth: 520px;";
                ExperienceEditor.Dialogs.showModalDialog(DialogUrl, '', dialogFeatures, null);


Only modification is the mapping of The Experience editor is now loaded with a direct link to ExperienceEditor.js Line 1.

Categories: C#, Javascript, Sitecore 8 Tags: , ,

Sitecore 8.1 Preview doesn’t match current site

01/12/2015 Leave a comment

With the release of sitecore 8.1 came a minor little config change, the resolve site configuration is now default false, previous version this was default set to true.


The settings is in 8.1 is set to default false

 <setting name="Preview.ResolveSite" value="false" />


when set to false the preview site, will always be set to what is configured in the following setting


<setting name="Preview.DefaultSite" value="website" />


Change the setting to true and Sitecore will try to resolve the sites matching a site from <sites> section.

Categories: Sitecore 8

Sitecore social connected Invalid Scopes: user_interests

12/11/2015 Leave a comment

I’ve set my self the task to have a go at the social connected, which I never really had a look at before.

So I’ve set it up a clean sitecore 8.1 and included the Facebook login in a MVC rendering and everything is working fine, except when trying to login on facebook, then I was shown an error See image below

The fix is pretty simple, fields that are pulled out of Facebook is configured in /app_config/include/Social/Sitecore.Social.ProfileMapping.Facebook.config and for the error i got it was the interest field that did’t exist in my user profile or had been renamed, but commenting out the field made, se below,e the error go away. the downside is that facebook interest isn’t mappen to contact details.


<!-- The interests listed on the user's profile. -->
<field enabled="true" originalKey="" sitecoreKey="fb_interests" permission="user_interests" access="/me/interests" text="Interests" /> 

I have to say my first impression of the module is it an great module easy to use and easy top configure, and can add a lot of value to any Sitecore solution

Categories: Sitecore 8, Social Tags:

Running Sitecore Field Editor from a Speak Command in Sitecore Experience editor

02/03/2015 10 comments

This post is an update of an old post . Sitecore 8 brought along speak and deprecated the old solution presented in that blog post. So let’s speakify it and create a  new solution. Luckily Alister Berry provided an excellent blog post about creating simple custom ribbon in the experience editor – So go read the post a comeback when your are done J.  For the rest of this post the button or functionality, if you like, will be to edit the HTML metatags ie. Title, meta-description, meta-keywords.

So let us begin with creating the button. Start Visual Studio launch the Sitecore Rocks and go to the Core database and navigated to “/sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Page Editor” under the item create a new folder and the the newly created folder add a new Large button Fille out the fields as shown below.








So next step is to and a layout to the new button select the button and choose “Design layout” in Sitecore Rocks – shortcut “ctrl + u”, and choose and a new rendering “Large Button”









Next lets add the properties required for the solution to work

The properties are Click is “trigger:button:click”, Command “LaunchFieldEditor”, PageCodeScriptFileName : “PATH TO THE JS FILE WE CREATE NEXT”







Okay now we need to create PageCodeScriptFile:

define([&quot;sitecore&quot;], function (Sitecore) {

Sitecore.Commands.LaunchFieldEditor =
canExecute: function (context) {
return true;
execute: function (context) {

context.currentContext.argument = context.button.viewModel.$el[0].firstChild.alt;

context.currentContext.argument = context.button.viewModel.$el[0].title;

Sitecore.ExperienceEditor.PipelinesUtil.generateRequestProcessor(&quot;ExperienceEditor.GenerateFieldEditorUrl&quot;, function (response) {
var DialogUrl = response.responseValue.value;
var dialogFeatures = &quot;dialogHeight: 680px;dialogWidth: 520px;&quot;;
Sitecore.ExperienceEditor.Dialogs.showModalDialog(DialogUrl, '', dialogFeatures, null);


Rather simple file which calls some server side code.  Also note that the settings will be save to the item when the ok button is clicked right away not need to click the save button in the experience editor.

public class GenerateFieldEditorUrl : PipelineProcessorRequest&lt;ItemContext&gt;
public string GenerateUrl()
var fieldList = CreateFieldDescriptors(RequestContext.Argument);
var fieldeditorOption = new FieldEditorOptions(fieldList);
//Save item when ok button is pressed
fieldeditorOption.SaveItem = true;
return fieldeditorOption.ToUrlString().ToString();

private List&lt;FieldDescriptor&gt; CreateFieldDescriptors(string fields)
var fieldList = new List&lt;FieldDescriptor&gt;();
var fieldString = new ListString(fields);
foreach (string field in new ListString(fieldString))
fieldList.Add(new FieldDescriptor(this.RequestContext.Item, field));
return fieldList;

public override PipelineProcessorResponseValue ProcessRequest()
return new PipelineProcessorResponseValue
Value = GenerateUrl()

Now lyou should  register the Request processor open the this file “Sitecore.ExperienceEditor.Speak.Requests.config” found in App_config/include folder. And add the new processor.

&lt;request name=&quot;ExperienceEditor.GenerateFieldEditorUrl&quot; type=&quot;PT.Framework.SitecoreEditor.GenerateFieldEditorUrl, PT.Framework.SitecoreEditor&quot;/&gt;

Just before we see the result there a few things that are nice to know. Because the server side code actually does a bit more the just returning and url for fieldeditor.  The creation of the URL Handle also besides creating a URL to the fieldeditor is storing required parameters in the current session in the urlhand id. The fieldeditor then pickups on parameters by going in to the session with hdl-id see url below. Hdl=F60F9A3AB4DC4CC8A7E28D25C4EC13B8


Okay now to the tricky part we need to pass in which fields we want to edit to the server class GenerateFieldEditorUrl,  unfortunately the parameter part of the layout isn’t rendered out and can’t be used but there are som simple ways we can force the fieldnames out in the HTML.

First you can edit the button item and set in the fieldnames in n the tool tips section




Alternatively you can set it in layout details page under tooltips, Be advised that if you choose this, editor will see the fieldname in the editors.





See the two different models below. The javascript in this post include selector for both option see comments in the js file






And now to the final result




So thats how you laucnh the field editor with a speak modal dialog, in the sitecore experience editor.



A problem with the two selector presented above is that they both requires you to add the fields to all language versions of the button item. So one of collegues Stephan Rifbjeg came up with a smart solution, simply to add the fields to the acceskey field on the layout see image below.


You can now get the value out with the following selector

context.currentContext.argument = context.button.viewModel.$el[0].accessKey;

Update from  kayeenl to catch the GenerateFieldURI

public class GenerateFieldEditorUrl : PipelineProcessorRequest<ItemContext>
public string GenerateUrl()
var fieldList = CreateFieldDescriptors(RequestContext.Argument);
var fieldeditorOption = new FieldEditorOptions(fieldList);
//Save item when ok button is pressed
fieldeditorOption.SaveItem = true;
return fieldeditorOption.ToUrlString().ToString();
}<span class="para_break"><i class="copy_only">
</i></span>       private List<FieldDescriptor> CreateFieldDescriptors(string fields)
var fieldList = new List<FieldDescriptor>();
var fieldString = new ListString(fields);
foreach (var field in new ListString(fieldString))
var descriptor = new FieldDescriptor(RequestContext.Item, field);
catch (Exception)
Log.Error(string.Format("Cannot create field editor for field '{0}'. Please configure the fields on the tooltip of the button", field), this);
return fieldList;
}<span class="para_break"><i class="copy_only">
</i></span>       public override PipelineProcessorResponseValue ProcessRequest()
return new PipelineProcessorResponseValue
Value = GenerateUrl()

Storring Sitecore Logs Using RabbitMQ Logstash Elasticsearch and Kibana (ELK)

31/01/2015 Leave a comment

In an earlier post I showed how to store Sitecore logs files in MongoDB see it here. Now I will demonstrate how to do the same thing using RabbitMQ, Logstash and Elasticsearch, and afterwards you can view and search in the logs using Kibana. It out of scope for this post to do any advance installation of the stack during this post. Also for the entire will be setup on localhost, if moved to a server additional configuration may be required.

So let’s jump right in and get RabbitMQ installed. So go to and download RabbitMQ and Erlang. See the marked download links in image below-


Erlang  dowload


Start running the Erlang installer the installation should be next … next and done  Next install RabbitMQ again next … next and done.
Now we need to install a add on to RabbitMQ this is easiest done by go through the windows start menu

In the command prompt copy in and hit enter
“rabbitmq-plugins enable rabbitmq_management”

Now you can navigate to http://localhost:15672/ The default username and password is guest and guest.
Go to the Queues tab and create a new queue call it Sitecore-Log and make it Transient


Perfect now with that in place lets get some code to push log entries to out newly created queue.
First lets create our Log appender

public class LogAppender : AppenderSkeleton
  public virtual string Host { get; set; }
  public virtual string UserName { get; set; }
  public virtual string Password { get; set; }
  public virtual string ExchangeName { get; set; }
  public virtual string QueueName { get; set; }
  protected override void Append(LoggingEvent loggingEvent)
   var message = LogMessageFactory.Create(loggingEvent);
   var messageBuffer = SerializeMessage(message);

  private byte[] SerializeMessage(LogMessage message)
   var serializedMessage = JsonConvert.SerializeObject(message);
   byte[] messageBuffer = Encoding.Default.GetBytes(serializedMessage);
   return messageBuffer;

  private void PushMessageToQueue(byte[] messageBuffer)
    RabbitQueue.GetInstance(Host,UserName,Password).Push(ExchangeName, QueueName, messageBuffer);

If created a simple LogMessage with the additional parameters that I want to log, like the Machine name ApplicationPoolNameand and the Sitename. So here is a factory tha can create a LogMessage from the LoggingEvent

public class LogMessageFactory
 public static LogMessage Create(LoggingEvent loggingEvent)
  var message = new LogMessage()
   ApplicationPoolName = HostingEnvironment.SiteName,
   InstanceName = Environment.MachineName,
   Level = loggingEvent.Level.Name,
   Message = loggingEvent.RenderedMessage,
   Site = GetSiteName(),
   Exception = GetException(loggingEvent),
   TimeStamp = loggingEvent.TimeStamp
  return message;

 private static string GetSiteName()
  return Sitecore.Context.Site != null ? Sitecore.Context.Site.Name : string.Empty;

 private static string GetException(LoggingEvent loggingEvent)
  if (!string.IsNullOrEmpty(loggingEvent.GetLoggingEventData().ExceptionString))
   return loggingEvent.GetLoggingEventData().ExceptionString;
  return string.Empty;
public class LogMessage
  public string Level { get; set; }
  public string Message { get; set; }
  public string Source { get; set; }
  public DateTime TimeStamp { get; set; }
  public string ApplicationPoolName { get; set; }
  public string InstanceName { get; set; }
  public string Site { get; set; }
  public string Exception { get; set; }

Next is the communication with the queue, This is done through a singleton pattern but use whatever implementation fit your purpose best.

public sealed class RabbitQueue
  private static volatile RabbitQueue instance;
  private static object syncRoot = new Object();
  private static IModel _queue;
  private static IBasicProperties _queueProperties;

  public static string Host { get; set; }
  public static string UserName { get; set; }
  public static string Password { get; set; }

  private RabbitQueue(string host, string userName, string password)
   Host = host;
   UserName = userName;
   Password = password;

public static void IntializeConnectionToQueue()
  var connectionFactory = new ConnectionFactory() { HostName = Host, UserName = UserName, Password = Password };
  var connection = connectionFactory.CreateConnection();
  _queue = connection.CreateModel();
  _queueProperties = _queue.CreateBasicProperties();

public static RabbitQueue GetInstance(string host, string userName, string password)
  if (instance == null)
   lock (syncRoot)
    if (instance == null)
    instance = new RabbitQueue(host,userName,password);
 return instance;

 public void Push(string exchangeName, string queueName, byte[] messageBuffer)
  _queue.BasicPublish(exchangeName, queueName, _queueProperties, messageBuffer);

Now lets add the new appender to web.config, use something like this

<appender name="RabbitMqAppender" type="RabbitMQLog4NetAppender.LogAppender, RabbitMQLog4NetAppender">
<host value="localhost" />
<username value="guest" />
<password value="guest" />
<exchangeName value="" />
<queueName value="Sitecore-Log" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%4t %d{ABSOLUTE} %-5p %m%n %X{machine} " />
<encoding value="utf-8" />

Lets add out new log appender to the default file appender so we still have log files written to disk. This means that we can set the queue to be transient, and not persistent.

  <priority value="INFO" />
  <appender-ref ref="LogFileAppender" />
  <appender-ref ref="RabbitMqAppender" />

Now you can start up Sitecore and you should start to see Messages starting to build up in the queue


Wuhuuuu now lets start putting the messages into elasticsearch via Logstash. Go to and download elasticsearch, Kibana and Logstash . Now lets start with the setting up elastichsearch After you have extracted the zip file you should see a file structure like the one below. Before you start the server edit the file elasticsearch.yml placed in the config directory at the end of the files add “http.cors.enabled: true”. Now go to the bin directory and launch the elasticsearch.bat.

Next we need Kibana, Make a new site in IIS setting the root the kibana folder it should look something like this.

Now we are almost done last part is logstash so in the directory where you have extracted logstash go into the bin folder
Create a new file call it test.conf and put in the following content

input {
  rabbitmq {
    host => localhost
    queue => "Sitecore-Log"

output {
  elasticsearch {
    host => localhost

Startup a cmd and go to the bin folder of logstash and run the following command
logstash-1.4.2\bin>logstash.bat agent -f test.conf

Now we done lets go into our kibana website and have a look Kibana comes with a default view for logstash See below.


With that in place we can start seeing our log entries.


Choose what is shown by selecting on left side


You can see details about individual message by click on them se example below




In the top you can add your own filtering and search in through the log entries


That was the first post in 2015, and the first post that for Sitecore 8.

Alexander Smagin  have also done something like this see his blog here