Sitecore XC 9.0.3 – Architectural thoughts on how to grab / pass and persist entities

Today I would like write about a quiet important topic for developers in Sitecore XC, how to persist entities in commerce engine. Once you start implementing your own plugins most probably you will also add new blocks, pipelines and command. And of course if you do that, you will most probably have to manipulate / change data of entities and save them back to Database.

Before I come to the point, where I show you a scenario I encountered in a customer project, I would like to start with writing about how in general the workflow how entities are retrieved from the system, and of course you can save them back after changing some data within your blocks.

Possibilities to retrieve an entity

Let us start with the basic topic of how to retrieve entities within a block. I would say there are basically 3 ways of doing that.

  • From Database
  • From Context
  • From Args

But how do these 3 method differ from each others?

From Args: Let me start with the way of retrieving an entity via args. I guess it’s the most obvious and easiest way of getting an entity. Once you create a block you have to also give the block input and output parameters depending on the location, where you would like to hook in. For example if you would like to create a new block for the IAddCartLinesPipeline and want to hook n between AddCartLineBlock and AddContactBlock, you can see the output parameter of AddCartLineBlock is Sitecore.Commerce.Plugin.Carts.Cart and the input parameter of AddContactBlock is also Sitecore.Commerce.Plugin.Carts.Cart.

2019-03-21 09_50_30-Customer.Sample.Solution - Microsoft Visual Studio (Administrator)

So to properly hook into that pipeline at that location, just create a block with input type matching the output type of the previous block and output type matching the input type of the next block.

2019-03-21 09_53_48-Customer.Sample.Solution - Microsoft Visual Studio (Administrator)

If your new block now needs to modify the given cart, you now can easily access it via args object of the Run method, modify it and pass it on to the next block.

2019-03-21 09_57_56-Customer.Sample.Solution - Microsoft Visual Studio (Administrator)

From Context: The next possibility to get entities within your block is to use the given CommercePipelineExecutionContext. Such an approach you have to do if you want to access entities, which are not OOTB passed via arguments through the pipeline to your block. Within your block you just have to access CommerceContext and extract your entity and you are able to change data, which are automatically updated in context.

2019-03-21 10_16_52-192.168.101.10 - Remotedesktopverbindung

In this example we are in the standard RMA pipeline of sitecore. Within that pipeline an object of type ReturnMerchandiseAuthorization is passed through the blocks. In addition the corresponding order object is saved to context, where you are able to get it from. Of course one prerequisite of doing that is, that some previous block saved the necessary entity to the context, from which you now want to grab it.

2019-03-21 10_08_46-192.168.101.10 - Remotedesktopverbindung

From Database: The last option to get an entity to be able to change data is the most direct one. To do that you just have to use the IFindEntityPipeline.

2019-03-21 10_59_40-192.168.101.10 - Remotedesktopverbindung

The result of that pipeline is a new instance of the entity based on the current state of the Database.

Possibility to save an entity

Now let’s shortly talk about, how you can save an entity to database again. This step is absolutely necessary when working with entities. If you would not save the changed entities in the end of processing back to Database, all the changes you made within the execution, within the pipelines and blocks, would be lost again.

Basically it is quiet easy to do that. To save an entity to database, you just have to call IPersistEntityPipeline with your entity.

2019-03-21 11_16_50-192.168.101.10 - Remotedesktopverbindung

Real world scenario

Now with these things in mind, let us have a look at an example I encountered, while working with Sitecore XC. The graphic below shows a sequence diagram of a pipeline created / used in Sitecore XC.

Example Pipeline Execution (1).png

Within this execution you can see, which pipelines are called when and from whom. In addition it shows, where the entity comes from, which is necessary to process.

Let me shortly describe the given scenario. It all starts with the execution of a first pipeline. Based on the given arguments the first block in the pipeline just grabs the necessary entity from Database. Because this entity is not part of the arguments, which are passed through the pipeline, this block also saves that entity to context. After doing something the first block of the first pipeline finishes and the second block is executed. As you would expect it, the second block grabs the necessary entity from context and does various changes to the entity. In between this block itself executes another pipeline. The parameter of that new pipeline this time is exactly that entity, so it can be passed via arguments of pipelines and blocks. So the first block of that second pipeline uses that argument to also do something with the entity. This goes on till block two of the second pipeline. This block again executes a new pipeline to let something execute. But this time there is a break in architectural concept. The parameter, which is passed is just an id of the entity, which is needed later on. The only possibility of pipeline three to access the entity now is to grab it again from database. After that, this pipeline makes some changes to the entity and directly saves it back to database. Now the execution of pipeline three ends and after that also of pipeline two. In the end of pipeline two, there is a block, which takes the entity, which was at that time passed via argument from pipeline one, and saves the entity back to database. Then also pipeline two ends. Within the first, initial pipeline, now a block is executed, which is responsible for grabbing the entity from context and saves it permanently back to database to persist all the changes made in between.

What are the problems of that composition of pipelines?

The main question, you could also ask yourself at this point is:

How does the entity look like in the end of the overall processing?

The answer is quiet clear. It does not look like we would expect it to be.  What I observed in the given scenario was an entity, which was in deed saved a few times, but always with a different state. Let me also describe, what most probably led to the inconsistency within the system.

As you know it from the beginning, we have multiple ways of getting an entity and that we always have to persist an entity to permanently save it. Within the given scenario, we have the problem, that all the ways of retrieving an entity for processing is mixed up together.In our scenario the main pain point lies in Pipeline 4 Block 1. This pipeline completely ignores given context and object within that context. The reason was quiet obvious. The pipeline was initially not designed to be placed, where it was finally placed, so it was not know, that there is an object in context, which can be used at this point, and more over, depending on the scenario, where it is used, there is not always a given entity in context, which could be used. In our scenario Pipeline 1 Block 1 prepares the context. If these pipelines are not there on other scenarios, also the context would not be prepared.  But the workaround, which was approached there lead to the visible inconsistency.

Assume you have your entity and you are changing it within your pipelines and blocks. These changes are saved in the end to context. Now, when we enter the last pipeline, we grab a new instance of our entity from database. This results in a new entity, which of course does not include all the changes made earlier in the execution. Within that block we make some new changes like adding a necessary component with additional information. Once we save that entity it is permanently saved to database. The result is an updated entity in database, which only includes the changes of that specific block and nothing more.

Now, we could imagine, we have to scenarios. The first would be, that this new entity is given back to the previous blocks and pipelines and then be used in context. The other scenario would be to return nothing and just continue working on the saved entity in context. Let me say at this point, that both approaches are not optimal. It would only shift the problem and only the things, which are lost and overwritten would change.

In out scenario nothing was returned, so we continued working on the context entity object. In the end we know, that the last block now grabs the context object and again saves that entity to database to permanently save all the changes made while execution. But because, we never returned the new entity from the last pipeline, our context entity does not know these changes and on our last save, these changes are not included. In the following graphic you can see the operations, which directly have an influence on each others.

2019-03-21 13_18_42-Example Pipeline Execution_ Lucidchart

The reaction of the commerce system to such scenarios is now quiet different.  In best case you directly get a commerce engine error, which tells you that there is a concurrency exception, that the version you try to save is outdated.

“MessageDate”: “XXXXXXXXXXXXXXXXXX”,
“Code”: “Error”,
“Text”: “SQL:block:persistentity.Update.Exception: SQL.UpdateEntity.Fail: Id=’Entity-Catalog-Support Dummy’|Try=’1’|Environment=’Entity-CommerceEnvironment-HabitatAuthoring’|Message=’Concurrency error: The Entity version supplied (3) is no longer the current version.’|Number=’50000’|Procedure=’dbo.sp_CommerceEntitiesUpdateWithSharding’|Line=’26′”,
“CommerceTermKey”: “SQL:block:persistentity”

In worst case, the save is successfully executed AND the changes you made in between are completely overwritten.

Now imagine you would have returned the changed object back to the previous block and that you would have updated the context. Of course this would have saved the changes made in pipeline four. BUT because you would just overwrite the context object and you grabbed the entity from database, ALL the changes made earlier would be completely lost and overwritten at this point. So the issue would only be shifted.

What should be done?

Now the question is, how can you get rid of all these problems and issues?

The answer of that is also quiet simple. Do not make things more complicated, than they are already. Of course it is possible to call pipelines within pipelines within pipelines and split up the tasks. But then you have to keep an eye on every single pipeline; what goes on, what comes out, what is present in context. And all the time try to avoid grabbing exiting and adapted entities again from database.

In general, when you design a pipeline always keep in mind, that one of the first blocks checks and initializes everything and that, if possible, just the last block is responsible for saving the entity. If you work with pipelines in between, keep in mind to give the new pipeline the current entity and also to take it back after execution, so all the changes are just made on one single instance of the entity.

Conclusion

Within the today’s article you had an insight in a real world scenario I observed in a customer project. You learned about, how to get, handle and save entities in pipelines and what issues might happen, if you are not aware of what all the pipelines and blocks do while execution. In the end you also got some personal hints to also avoid such scenarios and get consistent data in the end.

Sitecore Commerce Connect – Connecting Sitecore XP and XC

Within this article I would like to deal with some groundwork regarding Sitecore XC. As hopefully all of you know Sitecore XC is an extension to standard Sitecore XP, which enriches Sitecore with a powerful commerce engine. The big question is:

Does everyone of you know how exactly XP and XC are connected, and how you can have influence on this connection?

To answer that question, I would like to give you a general overview of that connection layer, which is called Commerce Connect.

Therefore I would like to start with the standard definition Sitecore gives us within doc.sitecore.net.

“Sitecore Commerce Connect is the Sitecore commerce API for storefront developers and is an integration layer between a front-end webshop solution and a back-end external commerce system. The back-end system can be any e-commerce system for which Commerce Connect connectors have been created by Sitecore or a third-party vendor.”

Architecture

Now we want to have a look, how this Commerce Connect is integrated within a common commerce scenario with XP and XC components and where we can see that piece of software. For that, let us have a look at the following graphic.

2018-10-19 19_32_15-Sitecore XC From A to Z.pptx - PowerPoint

This graphic show a standard architecture overview of a standard Sitecore XC integration. As a base we always have standard Sitecore XP, at this point with related software like, SIF and SxA, which we optionally can use for Sitecore XC. On top of that we have the commerce engine of Sitecore XC. Now highlighted the imported area of the diagram, where we can see the connection of XP and XC. Commerce Connect is installed with the installation of two packages “Sitecore Commerce Connect Core” which installs the basic Commerce Connect module and “Sitecore Commerce Engine Connect” which installs very specific functionality, which is used to implement the connection between Sitecore XP and XC. This package, patches all the general implementations, with concrete implementations for Sitecore XC. Commerce Connect in the end then acts as a middleware with which it is very easy to communicate with the commerce engine via standard and predefined interfaces, pipelines and so on.

Now lets have a look, what we get, when we have installed the Commerce Connect packages. This is especially imported, if you have the need to add, delete or modify something for your custom business needs.

Items

Lets first investigate the items we get. In the content editor we get a new area called “Commerce” as you can see below.

2018-10-19 19_35_49-Sitecore XC From A to Z.pptx - PowerPoint

In scenarios, where you connect other external commerce systems to Sitecore XP, this area is even more imported, than in the case, where we integrate Sitecore XC. The most imported sections under the Commerce item are

  • Commerce Control Panel
    • Commerce Engine Settings
      • Commerce Terms
      • Shared Settings
      • Storefronts

Nowadays the section Catalog is not used anymore from the Content Editor, because Sitecore XC has its own tool for handling Commerce Catalogs, the Merchandise Manager. Therefore the Sitecore recommendation is not to use Content Editor anymore for dealing with  catalog data.

Within the section Commerce Terms we set all the commerce related texts, which are used within the Sitecore XC Business Tools. Lets have a look how, with the example of adding a custom condition to the Promotion Manager. To add a custom condition it is enough to create a class like seen below.

2018-10-21 13_47_42-Customer.Sample.Solution - Microsoft Visual Studio

Within the ConfigureSitecore file just register the new rules and conditions with the following command.

2018-10-21 13_55_14-Customer.Sample.Solution - Microsoft Visual Studio

After you did that, you have only one single step left to do. Now you have to go tho the Content Editor under the Commerce Terms section and find, in this case, the area for Conditions. There you add a new Item, which has exactly the same name, than the used in the Attribute EntityIdentifier. Within this Item you now can add your individual text for your new condition. You can also use placeholder for custom input with the syntax [PROPERTYNAME] and a property within you class of type IRuleValue<TYPE>. 

2018-10-21 13_50_31-Content Editor

If you correctly did that, you can just open the Promotion Manager and the under the conditions list your custom condition with your individual text.

2018-10-21 14_11_56-HappyHour

2018-10-21 14_12_17-HappyHour

You can see the new condition with its entity name, and if you choose it, choose your custom input, in this case StartHour and EndHour.

I think the sections Shared Settings and Storefronts are quiet self explaining. Within Storefront you create your individual Storefronts for you Sitecore instance and link them to the specific environments, these storefronts should use.

NOTE: Currently there is a bug in the choice of environments. The field for choosing an environment was deleted in the last version, so for every storefront Sitecore always falls back to the standard environment, which is set in the /Y.Commerce.Engine/Sitecore.Commerce.Engine.Connect.config.

2018-10-21 14_07_01-C__inetpub_wwwroot_commerce.sc_App_Config_Include_Y.Commerce.Engine_Sitecore.Com.png

To get rid of that, just go to the Storefront template and add the field again to the template

On the left side, we see, how the field should look like, in the example of Sitecore Commerce 8.2.1. On the right side, we see, that the Environment field is gone within Sitecore XC. The logic in the background is still there, so it is enough to manually add that field again to storefront template. Sitecore already registered that as a bug.

Pipelines

Now lets go on to the next stuff, we get after installing Commerce Connect.

As you can see in the graphic above we get a bunch of new config file and within these configs a bunch of new commerce related pipelines. These pipelines are an essential part of Commerce Connect. Within the graphic above you can for demonstration reason see the AddCartLines pipeline. The left graphic shows, what is installed within the standard Commerce Connect packages, from Sitecore Commerce Connect Core. There we only get a standard pipeline with some really basic processors, which in the end only trigger analytics events and handle xDB stuff. The magic we get with a new config file, which we get after installing Sitecore Commerce Engine Connect. The right graphic shows, that the new config file patches the existing pipeline with custom processors, especially e.g with the processor AddCartLines. These patches and processors hold all the business related logic to establish a proper connection to the external commerce system, in this case Sitecore XC. These processors in the end make the rest API calls and communicate with the commerce engine. Both configs together build a fully working and functional pipeline to on the one hand trigger external system logic, and on the other hand track everything within Sitecore XP xDB.

The question now is, how are these pipelines  be triggered. The answer comes in the next chapter API.

API

Last but not least, what I want to mention within my article is the OOTB available API Sitecore Commerce Connect gives us to interact with external commerce systems. From the previous chapter, you already know, that we got a bunch of different pipelines. Now we see, how we can trigger these pipelines from code.  Sitecore Commerce Connect is delivered with a various number of so called Service Provider. If you use these service provider from Commerce Connect, in the end the corresponding pipelines are called and executed and you do not have to take care of anything else, just using these service provider correctly.

Bild3

Above you can see such a service provider call from an implementation of Sitecore Comemrce 8.2.1. As you can see, there is some piece of business logic with grabs the parameter, checks them and builds up the necessary request object for our commerce connect call. Then the commerce connect call, in this case, UpdateCartLines is executed with its request object. As result we get a very specific result object, which holds the information, if the call was successful, if not the error, and the inner object, in this case the modified cart object, which we then can use for our further purposes.

All these Commerce Connect calls are structured in the same way. They have their own request and result object, and only have to be triggered correctly.

Within Sitecore Commerce 8.2.1 we still had to implement our business logic around the commerce connect service provider.

But from Sitecore XC on, we do not have to do that anymore, cause from that time on, Sitecore integrated commerce functionality into the SxA including such implementation for commerce connect service provider.

As you can see in the image below, you can find these implementations in the DLL Sitecore.Commerce.XA.Foundation.Connect.dll und the namespace Sitecore.Commerce.XA.Foundation.Connect.Managers2018-10-19 19_44_14-JetBrains dotPeek

There you can find the various Managers to interact with Commerce Connect, like CartManager, CatalogManager etc.2018-10-19 19_44_27-JetBrains dotPeek

If you have a closer look at on of these Managers like the ICartManager, you can see all the available implementations, which can be used within your Sitecore XP solution, without the need to write a single line of code.

2018-10-19 19_45_21-JetBrains dotPeek

Note: If you reflector through the implementations, you will notice, that some of the functionalities of Commerce Connect are not implemented right now. These functionalities, then would have to be implemented by you on XP and if necessary on XC side, to be fully working.

2018-10-21 14_35_08-JetBrains dotPeek.png

Conclusion

Within this article you learned how Sitecore XP and XC are connected. You saw the different parts like, items, pipelines and API you get with the installed middleware. And especially how you can influence the standard behavior and where you have to make your changes for your custom business needs.

Sitecore XC 9.0.2 – Walkthrough of creating your own product importer with various pitfalls

Sitecore XC 9.0.2 – Walkthrough of creating your own product importer with various pitfalls

This time I would like to show you, how to create a custom product importer within Sitecore Commerce Engine as a custom plugin. For demonstration reason I also created a small github repo with all the code I present within this article.

Note: This code should be used only for demonstration and learning purpose. It has not been tested extensively right now, and should give you only an idea, of how to create your own importer within Sitecore Commerce Engine. Based on that implementation, your development could be much faster, without stepping into every pitfall 😉

Idea

If you followed my blog posts, you will have noticed, that I have already written about the engine in general, revealed some misunderstandings in architecture and concepts and put everything together to create a new demo plugin based on some real customer business needs.

This time I though again about a topic, which comes from real world requirements and which might be complicated to implement without any previous idea or help. The outcome now is a plugin, which demonstrates, how to import all kind of commerce stuff related to a catalog.

Basic Architecture

The basic architecture used by commerce engine in general consists of Pipelines. Examples of such pipelines are ICalculateSellableItemSellPricePipeline or ICreateCategoryPipeline. Pipelines itselves consists of a various number of Blocks, which are executed one after another, while running through the pipline. If you want to have a look at all the pipelines and blocks used by commerce engine, you can read about it in the Chapter The Node Configuration File explained below.

The NodeConfiguration file explained

Beside the standard commerce engine log file, you can additionally find a NodeConfiguration_***.log file under /wwwroot/logs folder, like seen below.

2018-09-09 13_42_32-logs.png

For every startup of the application such configuration file is created. It holds all the information about used and configured pipelines of the current commerce engine.

2018-09-09 13_42_01-_C__inetpub_wwwroot_CommerceAuthoring_Sc9_wwwroot_logs_NodeConfiguration_Deploym.png

An example of such a NodeConfiguration file you can see above. In the beginning it has some basic information about the instance. After that the structure is always the same. You see a pipeline with its same and parameter and with a small indent all the blocks also with parameters.

2018-09-09 13_39_57-_C__inetpub_wwwroot_CommerceAuthoring_Sc9_wwwroot_logs_NodeConfiguration_Deploym.png

Above you can see one specific pipeline, the IGetSellableItemPipeline in detail. In red you can see the fully qualified name and in brackets the parameter used by that pipeline. In yellow I highlighted all the block, which belong to the IGetSellableItemPipeline. There are blocks like GetSellableItemBlock or GetSellableItemCatalogBlock.  If this pipeline is executed all the blocks are respectively executed one after another from top to bottom. In green you can see two types highlighted. Every pipeline and every block consists of those information. The first parameter describes the input paramter used by the pipeline or the specific pipeline block. And the second parameter describes the output in the end.

Note: The output parameter of one block has to match to the input parameter of the next block 😉

Of course you are always able to create your own pipelines within your plugins from scratch or hook into existing pipelines by adding your own blocks. This is done by adding them correctly within the ConfigureSitecore.cs file. An example of such a configuration is seen below.

2018-09-09 13_59_18-Customer.Sample.Solution - Microsoft Visual Studio.png

The Magic of Pipelines & Commands

The question now is, how do we build now our own import functionality with these information?

If you have a closer look to all the Pipelines, you will recognize, that there are a lot of pipelines we can directly use. For example we have all kind of pipelines to handle a catalog. The ones, which are interesting for us are for example CreateCatalogPipeline, GetCatalogPipeline, EditCatalogPipeline. The big advantage is, that these pipleines are parts of the commerce engine implementation, that they are already used by other parts of the commerce engine, for example within the UI interactions inside the Commerce Business tools and that they consist of all the blocks, which handle underlying functionality, like interacting directly with the database.

To use now such pipelines, commerce engine provides us with corresponding command classes. These commands are responsible for collecting needed parameters, creating the proper argument class, which the pipeline needs including verification and in the end to execute the corresponding pipeline properly. So we also get rid of all the logic to properly execute pipelines.

Whats import to know now for us is, that if we want to use commerce engine functionality within our custom plugin, we only have to find the proper command class, instantiate it and use its built in Process method to initiate the corresponding pipeline, which itself initiates the corresponding pipeline blocks.

Basic structure of the importer project

Based on the information we found out in the chapter before, we now can start implementing our own importer.

Below you can see the basic structure of the Plugin.Sample.Importer project.

2018-09-09 14_26_18-Customer.Sample.Solution - Microsoft Visual Studio

This implementation consists of

  • dedicated importer classes, each responsible for a specific commerce entity type (Catalog, Category, SellableItem, SellableItemVariation) within Services
  • dedicated input parameter classes for the importer within Models
  • an extension class for handling some logic within parameterDTOs within Extensions
  • and a Controller within Controllers, which acts as external interface to test all the implemented functionality with Postman.
  • Next Step: Next step would be to create an own Importer Minion within Minions, which interacts with an external PIM system, retrieves all the Catalog information, including Categories, SellableItems and SellableItemVariations and uses all the Services to import these information into the Commerce Engine.

Implementation of the importer

Now we will have a closer look at the individual implementations of the importers. Each one handled in a separated sub chapter, cause even if the basic approach of every importer is the same, importing a catalog, a category, a product, or variant, has its own pitfalls and procedures we have to obtain to get it work.

Catalog Importer

As we already know from the previous chapters, if we want to build our own importer, we can use commerce engine OOTB functionality to do so. So lets have a look at the implementation

2018-09-09 14_49_56-Customer.Sample.Solution - Microsoft Visual Studio

Above you can directly see all the commands used by my catalog import. There are basic ones like GetCatalogCommand, EditCatalogCommand or CreateCatalogCommand. But there are also some ones, which are not so obvious, that they have to be used for proper result. These Commands are for example AssociateCatalogToBookCommand, DisassociateCatalogToBookCommand for Price- and Promotionbook handline or AssociateCatalogToInventorySetCommand and DisassociateCatalogFromInventorySetCommand.

Maybe some of you ask yourself, how can you find out, that these commands are needed? The answer is again, as always, I reflectored the existing code and existing pipelines, like DoUxActionPipelineWithin that Pipeline every UX interaction is handled from the Business Tools, including creating and editing catalogs and other commerce entities. While reflectoring this pipeline, I found out about the existence of these pipelines and commands, which are needed to fulfill such needs.2018-09-09 14_50_14-Customer.Sample.Solution - Microsoft Visual Studio

All these commands of course can be instantiated via Constructor Injection as seen above. Maybe to now get an idea of why it is useful to have such kind of implementation ready, cause even if you use existing pipelines and commands, you have to know about them and use them properly, which is in deed not so easy without any experience or trial and error. But now lets have a look at the code.

The ExecuteImporter function accepts as parameter the current context, the previously mentioned parameter object and a flag if existing catalog should be updated if already existing.

2018-09-09 15_05_10-Customer.Sample.Solution - Microsoft Visual Studio

Now we can examine the single steps of importing / updating a catalog

  1. The first step of our function is, that we try to create a catalog based on the provided data. This command returns null if the catalog already exists, based on the provided Name. Otherwise it would return an instance of the created catalog.2018-09-09 15_05_19-Customer.Sample.Solution - Microsoft Visual Studio
  2. Next step if to check if the catalog was created previously or not to determine if it is allowed to be updated2018-09-09 15_05_25-Customer.Sample.Solution - Microsoft Visual Studio
  3. If the catalog was already existing, we now want to get this catalog from the commerce engine to work with that later on2018-09-09 15_05_33-Customer.Sample.Solution - Microsoft Visual Studio
  4. The next step is very catalog specific. It is about associating the current catalog to a Pricebook, Promotionbook and DefaultInventorySet. To achieve an edit within these properties, we have to be careful, when to call associate and have to be sure that, if it was already associated, it is disassociated before. The code below checks if the current catalog is already associated and if so, if the new association is different than before. If so it automatically disassociates the current book and associates the new one, if it is existing within Commerce Engine. For now these steps are done for both books and the inventory set in the same way only with the individual command.2018-09-09 15_05_42-Customer.Sample.Solution - Microsoft Visual Studio
  5. The last step now is to edit the current catalog entity and set the new information, including the information about Pricebook, Promotionbook and DefaultInventorySet.  Note: Be careful, that these information match the associations done in the step before! It is possible to add here other names, than used in the assoication commands and therefore produce a missmatch. Note-2: Currently there seems to be an issue with programmatic associations and the Business Tools UX. It is possible that, even when you correctly use the commands for association and disassociation, the UX will display wrong, old information even if the engine itself has done the changes correctly. You can check, that the engine already did the changes and the UX display old information, if you then want to manually disassociate the catalog from the price book, that this is not possible and ends in an error message, that the catalog is not associated to the price book, even if it is displayed in the list below.2018-09-01 08_05_48-Microsoft Edge.png So it is possible, that if you have changed the price book this way, the Business Tools will still display the catalog as part of the old price book, even if it is not anymore. Sitecore currently checks if the behavior is a feature wish or bug. Current Ticket ID is 515201. I will add a public reference number later on if one is existing2018-09-09 15_05_51-Customer.Sample.Solution - Microsoft Visual Studio

Category Importer

Next we will have a deeper look at the category import functionality. Compared to the catalog importer, this one is much less specific, as you will see below.

2018-09-09 15_34_30-Customer.Sample.Solution - Microsoft Visual Studio

You can directly see, that we don’t need that extensive number of commands. We only need commands for creation, get, edit, association and “disassociation”.

The ExecuteImport has also nearly the same strcuture, than it was with the Catalog importer. Only the paramerter object has a different type for the specific category needs.2018-09-09 16_49_09-Customer.Sample.Solution - Microsoft Visual Studio

  1. The first step again is, that we try to create a new entity, this time of type category. Therefore we build up the entity ID of the category.2018-09-09 16_49_16-Customer.Sample.Solution - Microsoft Visual Studio
  2. Next we check if the category already existed and if we are permitted to update it.2018-09-09 16_49_22-Customer.Sample.Solution - Microsoft Visual Studio
  3. If the category exists, we try to get an instance of that.2018-09-09 16_49_27-Customer.Sample.Solution - Microsoft Visual Studio
  4. With that instance we try to update the values of that category, in case it was not created previously. If it would be created previously, an edit would be useless, so we try to skip that step then.2018-09-09 16_49_36-Customer.Sample.Solution - Microsoft Visual Studio
  5. In the end, we have to handle parent associations of the given category. Based on the list of given parents, we associate each as parent with the current category. One special thing at this point is, that we have to be careful, if the parent is a category or the catalog itself. Therefore we have to build up the parentId string diffrently.2018-09-09 16_49_46-Customer.Sample.Solution - Microsoft Visual Studio

Note: Maybe some of your already have seen it. Within step 5, when we associate parents to our category, there is missing one thing, which is essential. Currently we do NOT disassociate parents from the current category. Based on the current associations on the category and the given parentName list from the parameters and the deleteRelationShipCommand it would be possible to also do that. But right now this is not so easy to raelize. Below you see, a first approach of doing that

2018-09-09 17_08_01-Customer.Sample.Solution - Microsoft Visual Studio

As mentioned earlier, with the deleteRelationshipCommand, everything would work well. The problem here is to get all the needed information. Parameters are SourceName, TargetName and RelationShipType. The first problem started with the relationshipType of type string.

What do we have to insert here? 

You can see within the comment above, that I found out, what the possible values are, which can be inserted. How I did that? – Again with reflection.

First I had a look a the DeleteRelationshipPipeline and saw the two block belonging to that.

2018-09-09 17_14_02-_C__inetpub_wwwroot_CommerceAuthoring_Sc9_wwwroot_logs_NodeConfiguration_Deploym.png

Then I examined the two blocks, till I found the place where the relationshipType is used and found out the possible values.

2018-09-09 17_13_36-JetBrains dotPeek.png

So this problem was solved. The next issue was now to fill sourceName and targetName properly. TargetName is no problem, cause its the current category entity. But the sourceName is a problem I did not solve till now. You can see, that I experimented with a hardcoded value, which worked perfectly fine. But how do I find out all the current associated categories / catalog from the current category, to find out which one is missing and therefore has to be disassociated. The category class holds information about parentCategoriesList and parentCatalogList as seen above in the code snippet. But there properties only hold Sitecore Item IDs and not entity IDs of commerce engine. At this point I stopped the investigation and opened a Sitecore ticket, of how to properly retrieve a list of parent categories / catalog. Once I get these information, I can continue implementing the disassociation.

Product Importer

 The approach of the implementation of the product importer is nearly the same, than with the category importer. Therefore I will only show an overview of the whole process and will only point out some differences.

2018-09-09 17_47_30-Customer.Sample.Solution - Microsoft Visual Studio

Above you can the the whole process from creation, update check, product retrieval, edit and association, like it is also within category importer. Again we have here the disassociation not implemented, cause of the same reasons.

One special issue I encountered with the editSellableItemCommand. This command accepts an existing instance of a sellableitem as parameter. Therefore I first use getSellableItemCommand to retieve an instance of the current sellableItem, edit it with the new values like, displayName, Description, tags etc. and use that changed instance in the edit command. Unfortunatly this currently throws an harsh SQL server PK already existing exception. It seems that the edit command tries to create a new entity of that already existing sellableItem, which would explain the given error. This issue was also already reported to Sitecore Support.

Another strange thing with this importer was the usage of the getSellableItemCommand.  This command accepts an ItemId as parameter. At first I though I have to easily insert the entityId of the sellableitem, in the way I also added catalog or category entity IDs. The result was an error like this.

Expecting a CatalogId, ProductId and optionally a VariantId in the ItemId: Entity-SellableItem-0000004. Correct format is ‘catalogId|productId|[variantId]’.

So i changed my parameter to “HahniCatalogFINAL2|0000004”. But this produced exactly the same error. Therefore I started again to reflect the logic to see, what is expected as parameter.

2018-09-09 17_56_40-JetBrains dotPeek

What I learned from that piece of code is, that even if VariantId is not mandatory, I have to add the pipe separator in the end, so that we get an array of length 3 after splitting. Otherwise nothing works. So in the end my parameter looked loke this “HahniCatalogFINAL2|0000004|”, which finally worked well.

Variant Importer

Variant importer again looks very similair to all the other importer, especially the product import. Cause most of the time, if we try to access a variant of a product, we first access the product and then access the variants on that product to edit them and then save again the whole product. Therefore most of the used commands are the same, then in the products importer.

2018-09-09 18_07_27-Customer.Sample.Solution - Microsoft Visual Studio

Below you see the basic approach of creating and editing variants.

2018-09-09 18_05_21-Customer.Sample.Solution - Microsoft Visual Studio.png

The only thing we have to know at this point is, that when we want to access product variants, we do that in first getting the product itself and then accessing the variants, edit them and saving again the whole sellable item. At this place we again have the same issue with editSellableItemCommand than we hat with product importer. In addition we do not need to set any association, because this is already done on creation time, with giving the entity ID of the product name.

How to test the Importer

To test all the created fucntionality, I added a dedicated CommandsController, which is responsible to expose all the ExecuteImports from my importer for external usage. Below you see the example of the CreateOrUpdateCatalog function which takes all the parameter, builds the parameter object and calls the ExecuteImport function of the CatalogImporter. In a real world scenario you would either way use such kind of external inferface or especially with PIM imports a scheduled task(Minion) to do all that.

2018-09-09 14_46_58-Customer.Sample.Solution - Microsoft Visual Studio

This function is registered within ConfigureOpsServiceApiBlock with its name, parameter and return type as seen below. 2018-09-09 14_47_10-Customer.Sample.Solution - Microsoft Visual Studio

The ConfigureOpsServiceApiBlock itself is registered within ConfigureSitecore.

2018-09-09 17_28_06-Customer.Sample.Solution - Microsoft Visual Studio

To test the controller call you can simply use a postman, like seen below.

2018-09-09 14_47_38-Customer.Sample.Solution - Microsoft Visual Studio

Conclusion

Within this article you learned about some architecture regarding commerce engine pipelines and commands. With these information, we were able to create some basic importer to demonstrate the usage of these commands and how they work together. In the end we created some basic plugin, with which we are able to build a new catalog with categories, sellable items and variants of sellable items. We learned how to avoid some tricky pitfalls, and which command has to be used with which parameter, to save our valuable time in the future.

But nevertheless we still have some issues and todos left open with editing sellable items and variants after creation and some mismatch in displaying changed associations within Business Tools. Hopefully in the near future we will get some feedback on these issues to finalize the basic functionalities.

Next steps then would be

  • Create a minion as demonstration of external PIM system integration
  • Add importer functionalities to also import custom view properties generated with the Composer
  • Implement proper disassociation of categories and sellable items based on provided information by Sitecore Support.

Sitecore XC 9.0.2 – How to retrieve Composer generated Templates within Sitecore Engine

In this article, I would like to show you, how easy it can be to retrieve properties from sellable Items, which were created by the Composer within the Business Tools.  You only have to know how. 😉

Currently I am building a small plugin within Commerce Engine. For that plugin, I wanted to store some additional information on my sellable items in my catalogs. From the version 9.0.2 we already know, that we are now able to extend our commerce entities within Business Tools, more special with Composer. I already wrote about that in one of my previous blog posts. But a big question now was, how am I able to access these newly created properties within my commerce engine e.g. in a block of a pipeline.

After testing a bit and with the help of Sitecore support I finally was now able to reach that target quiet well.

Demo Scenario

Assuming the case you added a new view in the Composer and inside the View a new Property e.g. Taxes. Now you create a new plugin, find a pipeline e.g. AddLineITemToCart and want to extend that pipeline with a custom block. This block should now have a look at the item which is going to be added, and depending on the value set in the Merchandise Manager it should react and do something with that. Because the Composer uses its own structure and you have to know how things are composed and saved, its not so easy to get access to these values.

Retrieve any Component within Commerce Engine

In general you are able to access nearly everything with the same approach. Sitecore Commerce uses a feature called composition. Normally in a object oriented application, we use inheritance to extend models or entities. Commerce Engine uses composition. This means, we have a “standard” model. And this model is extended by adding all kind of other components to that model.

2018-08-01 14_27_39-Postman.png

In this example you can see a “standard” cart but extended with a custom porperty LoyaltyComponent added via composition.

2018-08-01 14_28_13-Customer.Sample.Solution - Microsoft Visual Studio

2018-08-01 14_47_37-Customer.Sample.Solution - Microsoft Visual Studio

To achieve that you just have to create that new Component and use that component on your basic model. The result of that piece of code is the json output you see earlier.

Retrieve Components from Composer

Basically the same technique is used also for retrieving stuff created by the Composer. Lets assume we extended our sellable item template with a new view Custom Plugin View and property Taxes.

2018-07-31 20_09_30-Customer.Sample.Solution (wird ausgeführt) - Microsoft Visual Studio

How do we now retrieve this 0.07 ?

Honestly its quiet easy. With the information above and some Sitecore help you can see the result below.

2018-08-01 14_50_19-Customer.Sample.Solution - Microsoft Visual Studio

This example shows within the AddLineItemToCartPipeline, how we can get from the commerce context at first the sellableitem behind the lineitem from the pipeline. Next it retrieves the ComposerViewComponent from that item. Thats exactly the view we can see within Merchandise Manager. With this information we can the concrete composer view with the correct key in the next step. In the end we just have to access the properties list and access our needed property by key / name.  So within the taxValue property we exactly have the value stored we entered in Merchandise Manager within our view within our Taxes property.

The exact same ways you can enter various custom views, with various custom properties. It would not matter anymore. The general approach of getting that stuff is always the same.

 

Sitecore XC 9.0.2 – What has been changed?

After Sitecore released the new Sitecore XC some time ago and I was able to have a look at that new Version, I was really excited about that. One the one hand Sitecore finalized the transformation from old legacy Server to the new .NET Core Authoring System. But on the other Hand there were unfortunately some missing functionalities like easy template creation, publishing & versioning, commerce item deletion, or easy commerce user creation. Sitecore itself said, that all These missing functionalites are going to be added in the next Version- so 9.0.2.

Because of that I am even more excited to have a close look, what Sitecore added in that new release. For more Information just have a look at one of my previous articles Sitecore Commerce 9 – What is new?.

I know there are a lot of new features and improvements in this version, but in this article I would like to Focus on the new Features and changes Sitecore made, especially regarding the limitations I already figured out in the past and explained in some blog Posts.

Versioning & publishment of Commerce Item

From Version 9 on Sitecore totally removed the old legacy Microsoft commerce Server and replaced it completely with the authoring System based on .NET Core. So from now on every functionality had to be delivered by that new System. In the Microsoft commerce Server there was a technique called Staging which was responsible e.g. for a proper publishment of the commerce items like catalogs, products etc. The Problem now was, that this Feature has not been implemented in the Version 9.0.1. So there was the Problem, that CM and CD System shared all the commerce items and every Change on CM had a direct influence on the CD System. For the initial Problem just have a look at the detailed Explanation of an older blog post Sitecore XC – How to properly publish Commerce Items? 

With this new release Sitecore finally implemented a versioning & publishment of also commerce items. So from now on you can on the one Hand track changes made on commerce items and on the other Hand you are now able to Change commerce items and publish them at a time you define with a proper workflow mechanism. Most likely this mechanism is not the Standard item workflow, but a Special commerce workflow which is configured from inside the Business Tools, like already possible with Price cards and Promotions.

In one of the next blog post I will give a deep dive into that technique to have a look, how it is being used and what is special in using this especially for content authors and developers, so we can maximize the benefit of that Feature for the customers

Work with Commerce Templates

In older versions of Sitecore Commerce like 8.2.1 also the Feature of creating, adapting, deleting templates of commerce Content was taken over by the legacy Microsoft server. From Version 9 on this Server was totally removed, but also this functionality of manipulating templates of commerce Content was not fully implemented by Sitecore. The problem is, that commerce Content are no real items, and that templates of These items are only Synced with the external commerce system. A direct change withing Content Editor of These templates lead to a complete unexpected behavior of the commerce System. Sitecore XC totally relies on the data stored on the global and shared environment databases in the new entity structure. From within there, all changes are synced to sitecore to also have it within Sitecore XP. But changing it directly in the XP would not lead to a change in the XC functionality, which means, the Systems differ from each other, which lead to various errors. The problem now was, that it was obvisously not possible to Change templeates within Sitecore, but the feature to change it e.g. in the Business Tools, was not implemeted right now, which made it quit complicated to create your own commerce templates. For detailed Information just read an older blog post of me Sitecore XC – How to delete Commerce Items in Sitecore?

If you have a look at the release notes of the new release, the first new Feature is a so called Entity Composer within Business Tools to easily adapt commerce entities like adding custom Attributes. From what you can see in the Entity Composer Manual it is completly what was missing and should perfectly fill the gab described in my older blog post.

Of Course we Need to deeply have a look at this new application, how it works and if it is now really so easy to do all that. But at first look this look quiet promising for me. Of Course I will have a deeper look at that Feature in one of my next blog Posts.

Delete Commerce Content

While having a look at the older release of Sitecore XC and playing a bit with catalogs, categories and sellable items, I also tried to remove stuff which, was accidentally created. After searching for a while, I was not able to find any delete button within the Merchandise Manager. The only solution within the Manager was to disassociate items from each other, so they disappear. Other ways were deleting them directly from the SQL Server, which is possible, but quiet dangerous. See Details in the following article Sitecore XC – How to delete Commerce Items in Sitecore?

From what I can see in the Manuals and release notes, a deletion of commerce items is still not possible. The only Thing mentioned in the Manual is the disassociation of items, so they are removed then

Disassociate a subcategory from a parent category

If you disassociate a subcategory from a parent category, that subcategory and any subcategories or sellable items contained in it are removed from the catalog, unless the subcategory is already associated with other categories or the top level of the catalog. For example, if you have a subcategory of Refrigerators contained in the Appliances category, and a subcategory of Mini that is contained in the Refrigerators subcategory, and you decide to disassociate the Mini subcategory, that subcategory and all sellable items contained in it will be removed from the catalog. However, you can associate a subcategory and the sellable items it contains to a different parent category, or the top level catalog.

See Details in that Manual entry.  So by now the official way of removing unwanted categories or sellable items is to only disassociate them from each others. When I think about that procedure this also makes sense from the Analytics Point of view. Think of the following Scenario.

You create a catalog with some categories and some products. Now you are going to “remove” some products from your catalog because they are not sold anymore. What happens, if you remove the items is, that within Analytics you see a mystical item id which does not exist anymore e.g. in top sellers or other statistics. It is getting also getting worse if you later on want to add that product again. You would create a new Entity which creates a new item with a new item ID. So from that time on you also get two Analytics entries, which belong basically to the same product. This is most likely not wanted in production Environments. Therefore it is a good technique to just disassociate items and associate them again later on. We had already similar issues while implementation, which lead to the solution not to delete sellable items anymore in production, but to disable them and enable them later on if necessary.

But for development and testing Environments, it would be still a big Advantage to have some Kind of OOTB delete functionality, because if testing and development developers and users often create a lot of garbage you want to clean up from time to time.

So hopefully it is already now possible to delete commerce Content or it is going to be implemented in a later Version.

UPDATE:

As I have mentioned, within the official documentation I did not find any reference to a newly added delete functionality within commerce applications. But now that I have installed the latest Sitecore XC version, I was glad to finally see a delete button within Sitecore Business Tools.

2018-07-30 18_41_10-Microsoft Edge

2018-07-30 18_41_50-Microsoft Edge

Finally you can now delete catalogs, categories, products, variants with one click, as seen above.

Create Commerce User within Business Tools

On of the limitations of the older release was quiet annoying and not very obvious. Within Sitecore XC you are able to create Commerce User either way with the Storefront (SxA) and therefore the Commerce Connect API or directly in the Customer Manager within the Business Tools. Within the Storefront everything also went quiet well and the creation of the user worked perfectly fine. But when you tried to create a user within the Customer Manager you had the problem, that everything went well and a user is created. But on the second look, I recognized, that there was no password set within the creating and that there was no possibility to set it afterwards. So in the end this user was not really usable without a password. See this article for detailed Information Sitecore XC – How to create a Commerce User.

If I have now a look at this release and especially at the Manual of the customer Manager, I can see that some Kind of Password Managing in the Manager is still missing. From what I can see in the Manual you are able to do the following things.

A Customer Service Representative (CSR) or Customer Service Representative Administrator can perform the following tasks on customer accounts:

  • Edit customer accounts. This includes:
    • Editing names, phone numbers, and email addresses.
    • Changing the language associated with the account.
    • Changing or adding addresses to the account.
  • Track customer orders.

See the customer Manual for detailed Information.

To be sure, I will definitely have a deeper look after Installation to see, if it is really not possible  till now. But as always, the second way of customer creation still works and is the first choice of customer creation for Sitecore.

Possibility of data migration from 8.2 to 9.0.2

I did not mention some limitations here, because I never tried to make such an upgrade within my initial Analysis. But in deed in was not OOTB possible to migrate all your Profile or catalog data created in the old legacy Server to the new authoring System and the global and shared databases. The only way was to Export your data from the legacy Server via XML and write your own plugin to use that XML to Import them in your new authoring System.

With this new release of Sitecore XC Sitecore provided an OOTB command line tool to migrate all your data from legacy Server. Here you can find the tool and the guide for detailed Information. This will definitely be a huge benefit for all developers and Partners and will safe a lot of time and money, who have already implemented a Commerce solution based on Sitecore Commerce 8.2.1 and now think of an upgrade to the newest Version.

In one of my later blog post, I will try to do such a Migration and share all the made experiences with the new tool.

Summary

To sum up, this new release has a lot of improvements, bugfixes and new Features and I really think Sitecore again made a big step Forward to have a powerful and stable commerce System. A lot of limitations from the older Releases I recognized were now completely implemented together with a lot of other Features.

I am really excited to install this Version on my own to experience all These new Features by myself. Stay tuned for more deep dives and experiences…

Sitecore Rich Text Editor (RTE) – Customize the colorset automatically in a multisite context

Recently I got a customer request to customize the sitecore rte to use automatically an individual color set, depending on the the site context, where the rte is being used. Because I think that this requirement is quiet cool, it helps the content authors a lot and the solution is pretty simple but effective, i would like to share the solution with you.

For that i will first show step by step, how the rte can be customized in general by overwriting the common rich text configuration class. After that I will point out, how easy the adaption of the used color set is. And at the end I will describe in detail the architectural idea of adapting the color set completely automatically.

Customize your RTE

To customize your rte in general you have to follow only two steps.

First implement a new cs class e.g. “CustomRichTextEditorConfiguration”, which can basically look like this:

///
/// Custom RTE Editor Config Class
///
public class CustomRichtextEditorConfiguration : EditorConfiguration
{
   ///
   /// c'tor
   ///
   public CustomRichtextEditorConfiguration(Item profile)
   : base(profile)
   {
   }

   ///
   /// Overload of setup editor
   ///
   protected override void SetupEditor()
   {
      // Custom Code
   }
}

Based on that class you can start your customization and e.g. the the colors, stylesheets to use for the editor and so on…

Second we have to register that new class as our new Rich Text Editor Configuration class. We do that by simply add a new configuration file under “/app_config/include”

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="CustomizedColorSet" value="true" />
      <setting name="HtmlEditor.DefaultConfigurationType"
value="YOURNAMESPACE.CustomRichtextEditorConfiguration,YOURASSEMBLY"
patch:instead="setting[@name='HtmlEditor.DefaultConfigurationType']"/>
    </settings>
  </sitecore>
</configuration>

Thats all. Now everytime a RTE is beeing opened, your configuration class in the SetupEditor() is entered to execute your adaptions.

Set new colors

Normally, when you open the RTE without customization, you get a default set of colors provided by the rte itself.

2017-04-25 09_40_30-Content Editor

To customize that color set you easily use our previously built class. In that class we can access the stored color set and possibly modify it via the following way

base.Editor.Colors.Add("#FF0000");

where the inserted color is in hex format.

NOTE: If you easily add new colors this way, sitecore overrides the default color set and starts a new one.

2017-04-25 07_49_09-Content Editor

To handle that problem, store the default color set in a temporary variable and add these colors again to the rte if you want them to be displayed, too.

Automatically add a individual colorset depending on the site context

At first I want to say some words to the architecture of our multi site environment, so you get a better understanding, of the challenge and why the customer wants that kind of requirement.

In our project we provided the customer with a single page type, because the microsites are only one pager and a base set of various modules, like text, slider, maps and so on. The problem with the provided features, was, that all of the microsites at the end looked the same, because they uses all the same templates and the same standard styles. To solve that we provided the customer with a full possibly of customizing each microsite individually. That means, the content author can add content as he did before, but now can also set various style rules e.g. background colors, font colors, sizes, fonts and so on. With that feature each microsite got its own look and feel and each micrsoite could look totally different, depending on the requirements of a specific site. The basic approach or that was on the one hand side the introduction of an global setting item, which stores all possible values, the author can change, and on the other hand to use all these values to create the css for each site dynamically on save of that settings item.

2017-04-25 07_18_39-Content Editor

The wish of the customer now was, that when the content author adds an rte on the site the defined color set is generated out of the provided colors in the settings item, so the look and feel of the page and the specific corporate brand is correct, without searching the correct color in the default color set.

To solve that problem i did basically the following steps described as pseudocode

2017-04-25 08_25_37-unbenannt - TeXstudio

Note:

  1. The colorset has to provide a datastructure to removoe duplicated entries, otherwise every occurence of the color in the settings item is displayed in the color set of the rte seperatly.
  2. You can find out the current Item Id by accessing the query prameter of your httpcontext at the query string parameter “id”
  3. You can implement the Find Root Page simply by traversing up to the root item of your current Item. Do not use the current Site based on the url directly, because in a multisite context you cannot ensure, that a content author uses a dedicated url for content editing. In our cases e.g. the authors all use a common url to enter the sitecore backend. So the safest way of retrieving the root item is to find it based on the the location of the current item and traverse through the content tree.
  4. To identify if a specific Itemfield is a color field, we used a dedicated field name notation. All our colorfields start with the prefix “hex_” so we can easily identify them programmatically by checking on “startswith” or something like that.

The result of that implementation is the following. For demonstation reason I created two settings, a Red Color Setting and a “Raindbow” setting to demonstrate the difference after opening the rte.

The next screens show an extraction of the settings item together with its output in the rte

You can see that the color set of the rte is taken from the edited colors of the settings item. If an author changes entries in the settings item the rte automatically adapts itself to that changes.

I hope this little article helps some of you in customizing your rte.

Erfahrungen mit dem Sitecore Experience Accelerator

Nun gibt es den Sitecore Experience Accelerator (kurz SxA) schon eine Weile.  Allerdings gibt es nur relativ wenige Entwickler, die sich wirklich einmal bislang damit auseinander gesetzt haben. Da ich die Idee hinter dem SxA wirklich gut finde, war es nun auch für mich Zeit sich einmal detaillierter damit auseinander zu setzen. Den besten Rahmen hierfür bot der diesjährige Sitecore Hackathon, da eine der dort gestellten Aufgaben die Entwicklung eines neuen SxA Modules war. Bei diesem habe ich zusammen mit Sascha Heyer. und Marina Gluzberg. als Team “Sitecore Triumvirate” teilgenommen. In diesem kleinen Artikel stelle ich den Weg von der Ideenfindung über die Implementierung bis hin zum Ergebnis einmal dar und zeige, wie gut das Entwickeln mit dem SxA in der Praxis funktioniert.

Was ist der SxA

Für alle, die noch nicht wissen, was genau der SxA eigentluch ist. Der SxA dient in erster Linie dazu, die time to market also die sogenannte Phase 1 zu minimieren, umso Ressourcen, Zeit und Kosten zu sparen, damit diese in die wichtigen Anforderungen für bspw. Personalisierung, also eine Phase 2 investiert werden können. Weiterführende Details hierzu kann man bei Sitecore selbst oder diversen Blogbeiträgen, wie Initial thoughts on Sitecore Experience Accelerator (SXA) oder Sitecore Experience Accelerator – What It Is And Why It Matters nachlesen, da ich hier nicht speziell mehr darauf eingehen werde.

Ideenfindung

Kommen wir aber direkt einmal zum interessanten Teil, der praktischen Arbeit mit dem SxA. Das erste was hier anstand, war natürlich das Entwickeln einer Idee. Hier sind wir allerdings sehr schnell, nachdem wir uns die bestehenden Feature angeschaut haben, bei Forms ausgekommen. Wenn man den Bereich Forms aufklappt, erkennt man dort nur eine “Web forms for Marketers” (kurz: WFFM) integration.

2017-03-19 18_01_31-.png
Abb. 1 SxA Features im Bereich Forms

Da wir einerseits bereits in der Vergangenheit so unsere Schwierigkeiten mit WFFM hatten und wir hier klares Optimierungspotential sahen, hatten wir uns dazu entschieden ein neues Formularmodul für den SxA zu bauen. Der Leitgedanke dabei sollte sein das Pflegen von Formularen intiuitiver und einfacher zu gestalten.

Architektur

Da Sitecore selbst es als Best Practice ansieht, aber auch weil der SxA selbst diese Architektur nutzt, haben wir uns bei der Implementierung des neuen Features strikt nach der Helix Architektur gehalten. Das heißt einerseits die Strukturierung der Solution in die Bereiche Foundation, Feature und Project, anderseits, dass alle Bestandteile bspw. eines Featurs innerhalb des Featureprojekts liegt und keine Abhängigkeiten zu anderen Featuren existieren, sondern nur in die darunter liegende Foundationschicht. Abb. 2 veranschaulicht die angelegte Solution.

2017-03-19 18_07_50-Hackathon.Sitecore.Triumvirate - Microsoft Visual Studio
Abb 2. Aufbau der Solution

Hinsichtlich der konrekten Architektur des neuen Formularmoduls hatten wurde überlegt, inwieweit man eine einfache und intuitive Pflegbarkeit erzielen kann. Die Idee war nun, dass ein Redakteur zu Beginn eine Art Formularcontainer, ähnlich wie beim bestehenden Formmodul, auf die Seite zieht. Somit würde der Rahmen des neuen Formulars bestimmt werden. Ab hier soll sich nun das neue Modul vom bestehenden Abheben und weiterhin vollständig über die Toolbox des SxA pflegbar sein. Der Redakteur kann nun weiterhin entweder Formularmodule, wie einfache Eingabefelder, Checkboxen, Datepicker oder sogar den Sendenbutton in den Container plazieren. Andererseits allerdings auch alle anderen bestehenden SxA Module, wie Image-Text- , Slider-  oder Textmodule. Das besondere ist, dass sogar die gelieferten Splitter innerhalb des Formulars plaziert werden können, um so sogar innerhalb des Formuals Aufteilungen in Zeilen und Spalten zu untersützen. Dies ermöglicht es dem Redakteur vollständig individuelle Formulare mithilfe des Drag & Drops Features der Toolbox zu erstellen, was ein klares Alleinstellungsmerkmal gegenüber der bestehenden WFFM Integration darstellt.

Hürden bei der Implementierung

Da bei der Implementierung von SxA Featuren doch einiges zu beachten ist, stellte mich die Entwicklung neuer Module zu Beginn vor gewisse Herausforderungen. Allerdings muss ich direkt anmerken, dass mir die Anleitung “Walkthrough: Building a new rendering” hierbei sehr geholfen hat. Anhand dieser Dokumetnation war es gut nachvollziehbar, warum man genau, wann welche Komponenten benötigte.

An dieser Stelle würde ich gerne lediglich auf die beobachteten Probleme mit der Arbeit im SxA eingehen und an welchen Stellen es einige Zeit brauchte um das gewünschte Verhalten zu erzielen.

Die Implementierung der ersten Controller, Views und Rendering verlief noch vergleichsweise problemlos. Als wir jedoch das erste mal versuchten unsere neuen Renderings in der Toolbox auswählbar zu machen, trat das erste Problem auf. Wir haben im besten Erwarten einfach innerhalb von  “/sitecore/layout/Renderings/Feature/Experience Accelerator/” einen neuen Ordner mit dem Namen “Hackathon” angelegt, wo wir all unsere neuen Renderings abgelegt hatten. Diese hatten wir auch unter “/sitecore/content/Theme/Theme Theme/Presentation/Available Renderings” analog angelegt und hinzugefügt. Allerdings hat sich in der Toolbox nichts getan. Zum Vergleich hatten wir unsere Renderings in einen bestehenenden Ordner, wie Page Content abgelegt. Und natürlich wuden Sie direkt im Experience Editor in der Toolbox an der Stelle Page Content angezeigt. Es galt also unseren neuen Bereich “Hackathon” irgendwo zu “registrieren”, damit die Toolbox dies auch ausspielen kann. Da der Weg dorthin, doch recht umständlich ist, allerdings viele betreffen wurd, würde ich ihn gerne einmal hier beschreiben.

  1. Füge unter /settings/Feature einen Ordner mit dem Namen des neuen Moduls an
  2. Lege dort ein Site Setup Item vom Typ Site Setup Root an
  3. Füge ein Add Available Rendeirngs Item vom Type AddItem hinzu (Abb. 3)

    2017-03-21 10_43_12-Content Editor
    Abb. 3 Einstellungen am Hackathon Site Setup Item
  4. Füge unter /templates/Branches/Feature einen Ordner mit dem Namen des neuen Moduls an
  5. Lege darunter ein neues Branch Template an mit der Basis Available Rendering an
  6. Wähle nun in diesem Available Rendering Item mit dem Namen $name alle Renderings aus, die in der Toolbox auswählbar sein sollen. (Abb. 4 und 5)

Nach der Ausführung all dieser Steps kann beim Anlegen eines neuen Tenant das neue Feature asugewählt werden (Abb. 6) und es werden direkt in der Toolbox alle Renderings korrekt angezeigt (Abb. 7)

Das zweite große Problem trat auf, als wir anfingen, nach den ersten Rendering auch Themes zu customizen. Das Konzept, wie man Themes bearbeiten ist in der offiziellen Anleitung sehr gut und nachvollziehbar dokumentiert.

Allerdings ist der Prozess ein Theme zu exportieren, zu entpacken, die Dateien zu bearbeiten, das ganze wieder zu packen und dann wieder zu imporieren auf dauer sehr zeitraubend. In unserem kleinen Modul, kam es bereits vor, dass ich diesen Prozess mehrere Duzend male durchlaufen musste, insbesondere, wenn ich kleinere Syntaxfehler eingebeaut hatte, die ich erst erkannt hatte, als das Theme wieder in Sitecore integriert wurde.

Um das ganze etwas abzukürzen, habe ich einen Trick versucht, von dem ich aber in der Tat nur abraten kann. Sobald ein Theme in Sitecore angelegt wurde, liegt es innerhalb der Media Library unter “/sitecore/media library/Project” und dort unter dem Tenant Namen, wie in Abb. 8 beispielhaft erkennbar.

2017-03-21 11_02_37-Content Editor
Abb. 8 Teneantspezifische Themes in der Media Library

Innerhalb des Themes kann man dann auch sämtliche Ressourcen, wie Images, Styles und Skripte finden, wie in Abb. 9 beispielhaft erkennbar.

2017-03-21 11_04_36-Christian Handel says...
Abb. 9 Skriptresource in der Media Library

Ab diesem Punkt habe ich nun nurnoch das spezifische JS file via Download heruntergeladen, es bearbeitet und wieder hochgeladen. Dies funktionierte soweit auch wirklich gut, solange ich mich im Edit Mode bewegte. Die ernüchterung kam, als ich den Preview Mode öffnete und nichts mehr funktionierte. Das gesamte JS und CSS waren mit einem Schlag unbrauchbar geworden und es wurden JS Fehler mit dem Title: Namespace SX not found geworfen. Das einzige was noch halb, war das Theme zu löschen und komplett neu anzulegen und nach dem Schema der Anleitung zu arbeiten mit einem echten Export und Import. Hier gibt es sicherlich noch Verbesserungspotential im Umgang und der Plfege von Resourcen wie CSS und JS.

Resultat

Als Ergebnis nach 24 Stunden Arbeit während des Hackathons haben wir in der Tat eine erste Version des sogenannten “Form Composers” implementiert. Die Kernfeature des neuen Moduls sind

  • Leichtgewichtigkeit durch Reduktion auf Basisfeature und -funktionalitäten
  • Hohes Maß an Flexibilität durch Kombination von standard SxA und Formular modulen
  • Einfache Pflegbarkeit bspw. via Drag & Drop
  • Unterstützung von gängigen Standardformularfeldtypen, wie Single-Line-Text Checkbox oder Datepicker
  • Unterstützung eines Mailversands bei erfolgreichem Absenden
  • Untersützung von Pflichtfeldeingaben und Fehlerfallvalidierung bei nicht-Eingabe
  • Einfache Erweiterbarkeit mit neuen Feldtypen und Funktionalitäten

Durch den neuen Form Composer ist der Redakteur in der Lage auf einfachste Weise mittels Drag & Drop zuerst einen Container auf der Seite zu plazieren und diesen dann nach belieben mit weiteren Modulen zu befüllen. Diese Module können SxA eigene Module wie Slider oder Textmodule sein. Oder es sind die neuen Form Composer Feldtypen, wie Single Line Text, Checkbox oder Datepicker. Das besondere hier ist, dass sogar die SxA eigenen Splitter in Rows und Columns unterstützt werden, so dass der Darstellung des eigenen Formulars keine Grenzen gesetzt sind. So können bereits schnell einfache Formular zusammengeklickt werden, welche einfachste Anforderungen erfüllen, wie in Abb. 10 zu sehen.

2017-03-20 14_24_59-Sascha
Abb. 10 Pflege eines einfachen Formulars

Es können aber auch hoch-komplexe Formulare mit dem neuen Composer erstellt werden, welche in verschiedene Bereiche aufgeteilt ist, mit weiteren Modulen und weit verteilten Eingabefeldern. Ein Beispiel eines solchen Formulars ist in Abb. 11 zu sehen, wo wir zu Demonstrationszwekcen einmal eine Variation des Hackathonanmeldeformulars nachgebaut haben. Hier wurden in den Formularcontainer zuerst die verschiedensten Grids gepflegt, um eine geordnete Aufteilung zu erhalten. Innerhalb dieser Grids wurden dann sowohl standard Module, als auch eignee Formularmodule plaziert.

2017-03-20 14_24_04-Demo
Abb. 11 Pflege eines komplexen Formulars mittels des Form Composers

Das eingesendete Video zum Abschluss des Sitecore Hackathon 2017 zeigt auch noch sehr anschaulich, was alles möglich ist und welches Potential dieses Modul hat. Der gesamte Sourcecode mit Dokumentaion ist unter folgendem Repository zu finden, damit man sich auch selbst ein Bild der Implementierung machen kann.

So läasst sich sagen, dass mit diesem Ergebnis man bereits erkennen kann, dass es verglichsweise leicht ist, mittels des SxA neue Module zu bauen, oder bereits bestehende Module in Seiten wiederzuverwenden, um so individuell auf jeden Anwendungsfall oder Kundenwunsch eingehen zu können.

Fazit

Die Idee des SxA ist Webseiten schnell und einfach zu bauen. Nachdem ich nun einige Zeit damit verbracht habe die ersten eigenen Module und Seiten zu bauen, kann ich sagen, dass im SxA viel potential steckt. Mithilfe des Sets an Featuren kann man bereits viele standard Kundenanforderungen umsetzen. Mit der Zeit lässt sich dieses Set stets erweitern, so dass man diese auch für zukünftige Anforderungen nutzen kann. Theoretisch können während der Entwicklung von neuen Modulen, bereits mit dem bestehenden Set an Featuren Seiten via Wireframing gebaut werden. Mit den ersten Visual Designs kann bereits während weiterer Entwicklungen Content gepflegt werden. So erkennt man schon, dass viele Arbeiten, die früher seriell abliefen nun teils parallel stattfinden. Genau dieser Mehrwert hat in unserem kleinen Team bereits sehr gut funktioniert. Wir konnten auf bestehende Features des Sxa zurückgreifen und via Themes unseren individuellen Wünschen anpassen. Parallel zur finalen Contentpflege konnten noch weitere kleinere Implementierungen bzw. Themeanpassungen durchgeführt werden, so dass zum Schluss aus den gepflegten Wireframes, dem Content und den Themes die mit einem Klick eine fertige Seite entstanden ist.

Das praktische Arbeiten mit dem SxA zeigte an der ein oder anderen Stelle noch einige Schwächen. Es kam bspw. häufiger vor, dass der SxA bei der Pflege im Experience Editor leider noch abstürzte. Bei der Pflege bzw. dem Anpassen von Thems ist der Prozess das Theme erst herunterzuladen, zu entpacken, seine Änderungen durchzuführen, das ganze wieder zu packen und zum Schluss wieder zu importieren auf dauer sehr umständlich. In unserem Fall dieser Prozess einige dutzend mal durchgeführt werden, bis sowohl CSS als auch JS so waren wie sie sein sollten. Hier wäre es sicherlich sinnvoll dem Entwickler eine einfachere Möglichkeit zu geben Themes anzupassen.

Nichtsdestotrotz hat Sitecore mit dem SxA ein jetzt schon bemerkenswertes Modul erschaffen, welches das Potential hat die einfache Webseitenimplementierung mit Sitecore zu revolutionieren.