Showing posts with label configuration. Show all posts
Showing posts with label configuration. Show all posts

Friday, 22 January 2021

Fortis - Unable to find template error

I was upgrading my client's Sitecore instance lately and at some point I've spotted this issue with Fortis:

Fortis | Unable to find template for MyProject.Model.IMyTemplate

After doing some digging in the internet I couldn't find out what was causing it. I decided to compare all config files and I've spotted that my Web.config on new environment is missing these bits:

Declaration of Fortis section in  <configSections>

<configSections>
...
    <section name="fortis" type="System.Configuration.NameValueSectionHandler" />
...
</configSections>

...and the actual section my Model project assembly reference:

<fortis>
    <add key="assembly" value="MyProject.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</fortis>


With these added it all worked. I hope this will help somebody!

Sunday, 2 December 2018

Unicorn - disabling automatic items serialization

I've come across a problem with Unicorn last time. We deployed to QA environment and a couple days later testers started to see issues like this:

Unicorn: You cannot have a sparse serialized tree

It was appearing when they were saving edited content. I've decided that we don't really need automatic items serialization on QA and other environments, so it will be best to just switch it off. I took a look into Unicorn.DataProvider.config and the comment there states:

This file configures the Unicorn data provider. The data provider writes updated serialized items to disk when they are changed.
This file should be removed in ANY deployed instance (CE or CD) that does not act as a source for serialized item updates.
Generally speaking that's anywhere other than a developer workstation, so your CI process (you have one, right?) should remove this file during the build.
IMPORTANT EXCEPTION: If you are using Transparent Sync as a deployment mechanism, this file must remain on your CE environment.

That's exactly why it should be turned off on any non-development environments.

As we are using Sitecore 9, we have set localenv variable to Local on our dev instances Web.config

<add key="localenv:define" value="Local" />

Instead of removing Unicorn.DataProvider.config config file after deployment, I have added localenv:require="Local" to root element there:

<sitecore localenv:require="Local">
  <dataProviders>
    <!--
      Register the Unicorn data provider for use. If a database hooks to the Unicorn data provider it will
      automatically write changes to the database that match any configured predicate into the serialization provider.
 
      Changes that only affect Revision, Modified, or any fields ignored by FieldPredicates will be ignored.
    -->
    <unicorn type="Unicorn.Data.DataProvider.Unicorn$(database)DataProvider, Unicorn">
      <param connectionStringName="$(1)"/>
      <Name>$(1)</Name>
    </unicorn>
  </dataProviders>
 
  <!--
    Hook the Unicorn Data Provider into the master and core databases. If you're not
    syncing anything in core you can safely unregister it from here. If you want to
    sync something to another database register it here.
 
    It's safe to remove this config section on any environment where you are not
    collecting item changes, which may mean anywhere other than local development
    sites. This will avoid any performance hit from writing unused serialized files.
  -->
  <databases>
    <database id="master">
      <dataProviders>
        <dataProvider ref="dataProviders/main">
          <patch:attribute name="ref">dataProviders/unicorn</patch:attribute>
        </dataProvider>
      </dataProviders>
    </database>
    <database id="core">
      <dataProviders>
        <dataProvider ref="dataProviders/main">
          <patch:attribute name="ref">dataProviders/unicorn</patch:attribute>
        </dataProvider>
      </dataProviders>
    </database>
  </databases>
</sitecore>

That makes sure the changes made by editors won't be serialized.

Saturday, 7 April 2018

Configuring Unicorn on Helix project

Setting up synchronization in Helix based solution is one of the most crucial things. With proper configuration all new projects will be easy to maintain and predictable. In this short post I will describe basics of configuring Unicorn.

Helix structure configuration

First of all we should have our Foundation.Serialization project configured. In this project we should install Unicorn - from the nuget feed.

We should have whole Helix items structure configuration here and this one should be synched as the first in the queue.


There is unicornSourceFolder variable which should be pointing /src/ folder of our app code. We can specify it for example in some patch in Project.Common project.


 

Abstract configurations

It is really good idea to have some basic configuration we can inherit from. It can be placed in for example Foundation.Serialization project.





Then we can use this abstract configuration in our projects




We do it by using extends parameter

extends="SitecoreCoffee.Base"

If our project is relying on some other, e.g. from Foundation layer, then we should specify it by dependencies parameter. Here it depends on whole Foundation layer by using asterix

dependencies="Foundation.*"

...but it could be as well list of comma-delimited configuration names

dependencies="Foundation.Search,Foundation.Extensions"

As I mentioned earlier, Foundation.Serialization configuration should be synchronized as first, so the our patch should go after that one:

patch:after="configuration[@name='Foundation.Serialization']"

Don't forget to put descriptive name and description attributes too.

Project-specific configurations

In Helix every project which requires some serialized Sitecore items, should have it's own Unicorn configuration. Above we created Feature.Search project configuration and there we put only project-specific items in the predicate

<predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
    <include name="SitecoreCoffee.Feature.Search.Templates" database="master" path="/sitecore/templates/Feature/Search" />
    <include name="SitecoreCoffee.Feature.Search.Renderings" database="master" path="/sitecore/layout/renderings/Feature/Search" />
</predicate>

Even if you're not using Helix you should consider creating several small configurations instead of one monolithic. It will be easier to synch only specific ones in Unicorn synch panel.





Wednesday, 27 January 2016

Sitecore 8.1 - Creating custom search index

Sitecore provides availability to configure and use custom search indexes. Starting from version 8.1 they are slightly different in configuration. In this article I will provide you with some advices to create your own Sitecore search index.

Differences from Sitecore 8.0

Let's take a quick look at the differences from version 8.0. When you open Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config or Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.config, you can see that sections where we define included and excluded templates, fields etc. are now wrapped with documentOptions tag:

<documentOptions type="Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilderOptions, Sitecore.ContentSearch.LuceneProvider">
Also, names of the methods that includes/excludes specified elements now are different, for example,

<exclude hint="list:ExcludeTemplate">

is now replaced with

<exclude hint="list:AddExcludedTemplate">

That are the things I've conquered while upgrading from older Sitecore versions. Here's the list of changed names:

8.0 and before 8.1 and after
IncludeTemplate AddIncludedTemplate
ExcludeTemplate AddExcludedTemplate
IncludeField AddIncludedField
ExcludeField AddExcludedField
RemoveSpecialFields AddExcludedSpecialField

Creating custom search index

To define our own custom Sitecore custom index we will have to create config patch.

Here is version for Lucene

Here is version for Solr


Let's take a closer look now.

Extending default index configurations

Sitecore comes with default index configurations we can use to build our own index. There are versions for Lucene and Solr as well. To use it we are declaring ref attribute on <configuration> element:

<configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">

<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration">

Indexing fields

With this setting:
<indexAllFields>true</indexAllFields> 
we declare that all fields will be indexed. This is by the way default setting in default Lucene index configuration.

We can set it to index only specific fields - indexAllFields should be set to false
<indexAllFields>false</indexAllFields> 
And then we should set our fields explicitly
<include hint="list:AddIncludedField">
  <Title>{96970EAB-F8C6-4DE2-A124-CDAC2DFD0C90}</Title> <!-- Title -->
  <Content>{EC539DFA-07C1-49A4-A094-87EACF5ED9BB}</Content> <!-- Content -->
</include>

Our index will also contain computed fields that come from default lucene index configuration. If we don't want them, then we should base our index on edited lucene index.

Including templates

The most important setting is where we define included templates. Only these templates will be indexed:
<include hint="list:AddIncludedTemplate">
    <Article>{C2198DA4-C89F-45D9-AF1A-E24C97F83398}</Article>
    <News>{24EBFFC0-27F0-4F18-A425-74D62F21609E}</News>
    <About>{804B99A2-B18E-4B86-A862-4D0270D4DEAB}</About>
</include>

I have included three example templates, they are declared with:
<templateName>Template ID</templateName>

It is also important to set up root path for the crawler:
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
  <Database>web</Database>
  <Root>/sitecore/content/home</Root>
</crawler>

As we have complete index configuration lets save it in /App_Config/Include/OUR_CUSTOM_CONFIGS_FOLDER folder with file name format Sitecore.ContentSearch.Lucene.Index.OUR_INDEX_NAME.config. After that let's rebuild our new index.

Previewing indexes

After our index is built we can preview it. For Lucene indexes we can preview it with external tool named Luke (https://code.google.com/archive/p/luke/). It opens folder with index, usually located at Data/indexes folder:

Luke

For Solr indexes we basically open Solr Admin panel, by default set up on port 8983. We can access it by going to url http://localhost:8983/solr/

Solr admin panel


Querying index

As we have index built, we can run queries to get desired elements from index. Sitecore provides ContentSearch library and it is the proper way of searching index in Sitecore. It's completely independent from the implementation so switching index provider won't require code changes (in most cases of course ;)).

Here's a sample code that reads our custom index and searches for specified phrase:

var index = ContentSearchManager.GetIndex("SitecoreExperiments_index");
string phrase = "search phrase";
 
using (var context = index.CreateSearchContext())
{
    var searchQuery = context.GetQueryable<SearchResultItem>()
        .Where(x => x.Language.Equals(Sitecore.Context.Language.Name))
        .Where(x => x.Content.Contains(phrase));
 
    var resultItems = searchQuery.ToList();
    var totalCount = searchQuery.Count();
}

Sample project that provides custom search index and search service is available on my Helix project at GitHub - https://github.com/ReoKzK/SitecoreCoffee/tree/master/src/Foundation/Search/code

Sunday, 29 November 2015

Keeping your Sitecore configuration files clean

Keeping your Sitecore configuration files clean is very important thing for further upgrades and maintenance. I had a lot experience with projects where configuration files was edited and maintained poorly. This article will provide you with some points you should observe to keep your Sitecore configuration clean and transparent. 

1)      You should definitely avoid editing Web.config file. Rather than that you should use Sitecore patch files mechanism to change Sitecore configuration. In this mechanism, Sitecore processes all .config files in App_Config\Include directory and applies patches to Web.config file.
E.g when you want to replace pipeline processor with your custom one, you could simply edit Web.config. You could delete or comment line with processor you want to replace and write new one. This is the fastest way but the worst. The best way is to create custom patch file:

<!--
 
  Events configuration
 
-->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <events>
 
      <event name="item:creating">
        <handler type="SitecoreExperiments.Common.Events.PreventDuplicates, SitecoreExperiments.Common" method="OnItemCreating" />
      </event>
 
      <event name="item:saved">
        <handler type="SitecoreExperiments.Common.Handlers.CustomSaveHandler, SitecoreExperiments.Common" method="OnItemSaved" />
      </event>
 
    </events>
  </sitecore>
</configuration>

For more informations about configuration patch files see John West post: http://www.sitecore.net/learn/blogs/technical-blogs/john-west-sitecore-blog/posts/2011/05/all-about-web-config-include-files-with-the-sitecore-aspnet-cms.aspx

You can check how patches applied to Web.config file using special url /sitecore/admin/showconfig.aspx.

Unfortunately Sitecore patches concern only /sitecore branch in Web.config file.

2)      Group Sitecore patches into files that matches specified type of Sitecore region e.g pipelines, scheduling tasks, events. Also make sure that your patches are loaded last – put them in your folder in App_Config\Include and name it with prefix ‘Z_’.

3)      Make developer-specified patches ignored in code repository. Let developers use commited example file (with name e.g FileName.config.example) to create their custom one.

4)      Don’t make Web.config file ignored in code repository. Web.config should be commitable.

5)     Make sure that all Sitecore application configs are in solution. Leaving some of them just in webroot after some installations, leads to misconfiguration and nasty bugs.