For some time now, while working with Sitecore XC, I am struggling with the concept of policies. In general I really like that concept, how new policies are added to an environment and how things work. But more more I got requirements from customers, who wanted to be able to change those policies on their own. And of course you all now, that this is not possible. Policies are added, edited and maintained purely by developers. So either way you would have to exactly do that. Just change the setting all the time the customer wishes, or provide a smarter solution for that. And exactly that I tried to fulfill. Within this blog post I will first describe shortly the mechanism of policies and how they are maintained, will come back to he customer requirements, which are appearing more and more in all my projects and what that really means for us developers, till I finally present some extension for Sitecore XC OOTB logic to generically fulfill such requirements in an easy way.
Introduction to policies
If you are not familiar with the terms environments, policies and roles I strongly recommend you to read first one of my previous articles, which can be found here. But let me also try to sum up the essence of that article here a bit.
As you all might now, the normal way of storing any kind of configuration for Sitecore XC, is, to store it in a custom policy. A policy is nothing more than a piece of json file like seen below.
As you can see such a policy consists of 1 to n different properties, which can be set and maintained within that specific json file. These values are then mapped to custom .cs policy file to be then used ion runtime
Multiple of such policies are then combined together to one big environment Sitecore XC uses to execute pipelines, blocks commands and more for specific storefronts.
So in the end to speak in Sitecore XP terminology these polices are very similar to .config files or patches under the App Config/Include folder. As good as that works the trouble starts now in the way, of how such configs are maintained and deployed to other environments.
Process of how to bring changes of policies live
Boths types of configurations .config files and .json policies have the same weakness or better restrictions. They can normally not be maintained by content authors. The normal process of changing a value there and bringing it e.g. to production is in simple words the following
- Change the value locally
- Commit and push these changes
- Deploy this to the target environment
- Bootstrap environment so that json values are stored in DB to be used on runtime
So you can already imagine, that this is nothing an editor can do, and nothing, which can be done very quick. Because of that normally, in Sitecore XP you create global setting items, which can be maintained on runtime by content authors. Unfortunately nothing similar is existing in Sitecore XC – till now. ^^
Custom Settings plugin
So because I recognized, that there is definitely a lack in OOTB implementations, which make the life of content editors and developers more difficult, I thought, it makes sense to provide some new plugin to fill that gab.
What does it do?
With the newly created settings plugin you are now able to set previously defined policies values within a new BizFx application on runtime.
How does it look like?
In the screenshot below you can see the new application after integrating the setting plugin into a customer solution.
If you click on the settings application an overview of all existing settings is displayed. If no setting exists a default one is created automatically, which can be used.
In the standard implementation of settings plugin you have 4 actions available to interact with settings, which can also be seen in the screenshot below
Add: On click a new forms opens, where you can enter a Name and Display Name to create a new setting entity.
Remove: Removes the currently selected settings entity
Activate: Activates the currently selected settings entity. In addition it iterates through all other existing setting entities to disable them automatically, so there can be only one setting be active.
Deactivate: Deactivates currently selected settings entity
If you now click e.g. on the Default Setting entity, the corresponding entity view opens. After initially integrating the plugin, the settings entity will just have one single property is Active, like you can see below.
From this point on, you can now start filling the settings entity with all kind of policies you would like to edit on runtime.
How to integrate it into custom plugins?
So let’s start of how to integrate a custom plugin policy into the settings functionality.
Basically you need 4 different blocks to be able to display information in an accordion in an entity view, to provide an editor action on that accordion, to display a form to be able to edit properties and to be able to apply these changes to the current entity.
- EntityViewXXX (Used to display data in accordion view)
- FormEditXXX (Used in dialog to edit properties)
- DoActionXXX (Used to apply edited properties from FormEdit to entity)
- EnsureActionXXX (Used to provide edit button on new accordion view)
For all of you, who already extended entity views with new accordion views, know, that this needs some time to be fully implemented. Therefore the first thing I did for the settings plugin was, to make that process much easier for developer.
The settings plugin provides you with 3 different base blocks, which can also be seen below.
What you now just have to do to integrate your plugin into settings is, to create 4 different blocks and do the following steps
- Inherit from the corresponding base blocks of settings plugin
- Execute Base.Run method and provide policy as generic parameter and view or action name in function parameter
- Add all the new blocks to the specific pipelines in ConfigureSitecore.cs
Now let’s have a look at the whole code of the 4 blocks, where we use inheritance to use some basic functionality.
As you can see, the whole implementation of all these 4 blocks consists of just one single line of code, where you just have to tell the function, which policy and which view name (Entity View) or which action name (DoAction and Form Edit) to use.
Last but not least add all the 4 blocks now to corresponding pipelines, like seen below
Policy Property Attribute
In addition to the base blocks, which can be used in custom plugin, you now just have to use the newly provided EditorSetting attribute on already existing plugin policies. In the screenshot below you can see an example, where I added the new attribute to all properties of the PimImporterPolicy you already know from the beginning.
After you added these attributes to the policy and reload the settings entity again, you will now see, that a new accordion has been loaded with all the properties you previously added via setting the editor setting attribute.
And of course also the edit functionality is directly fully working like seen below.
And lastly, of course if you confirm changes, the piece of code is also already working, which applies these changes automatically to the current settings entity.
Note: As you might see, there are of course currently some limitations, like list handling, which will be covered in more detail as improvement in the future. Right now you can also edit lists, which are treated as pipe separated strings.
In case you do not want to use every property of the policy, you can easily remove all the attributes from the properties you would like to exclude from settings functionality.
In this example I removed the setting for start hour, end hour, pim endpoint because I do not want editors to edit such properties ^^. But in the end it is completely up to you, what you would like to be editable in settings entity.
Now, after we added our policy to the settings entity, we also want to use it in our code. To do that, I also created some piece of code to do that. The same way you retrieve policy from commerce context, you can now also retrieve settings policy.
- context.GetPolicy<T>() -> Grab policy from environment
- context.GetSettingPolicy<T>(CommerceCommander commander) -> Grab policy from active setting entity with fallback logic to grab policy from environment
Below you can the whole and simple implementation of GetSettingPolicy with integrated fallback logic.
If we now think of possibilities how we could use the new settings in custom code.
Different ways to use setting policies together with OOTB environment policies
- Overwrite whole policy
- In such case just use the new extension method context.GetSettingPolicy<T>(…) and continue working with the returning policy
- Overwrite just specific properties
- Use Standard context.GetPolicy<T>() AND context.GetSettingPolicy<T>(…) to retrieve environment and setting policy to decide later on, which property to be used when and which fallback logic shall be applied
- Completely standalone setting
- Note that such policies are not stored in environment and cannot be retrieved via OOTB context.GetPolicy<T>() call
- Use context.GetSettingPolicy<T>(…) to retrieve the setting policy
Because in our example, we removed some of the properties from the possibility to be edited in settings, we would have to apply approach number 2 from above. To do that, we first grab settings policy, beside with environment policy.
And then we can easily and individually apply our custom fallback logic for each property, like seen for mailsubject below.
Within this blog post I presented a newly created plugin called Plugin.Sample.Settings, with which you are now able to edit policy properties not only in json on development time, but also within BizFx tools in a new application on runtime.
This way it is much easier to edit specific settings per environment as developer or editor.
The whole code can be found in the following github repository
And as always, the code is not production ready and is not extensively tested. Therefore use this code as a starting point for your own implementation.