Sitecore – XM Cloud – Errors During Setup and Fixes/Work Around

This is the second part of my XM Cloud series, as mentioned in the end of my previous post, sharing the issues I faced while setting up XM Cloud instance and what I learned in the due process of fixing them, hoping it comes handy in troubleshooting the similar issue if you come across.

Deployment failure due to license:

                The first time when I spined  up my instance, I faced the below error. I was truly flabbergasted as I didn’t use any custom code. I used the default starter project which XM Cloud offered.

Starting deployment of environment 'DEV'
Starting deployment settings encryption
Encrypted deployment settings
Starting deployment configuration
Deployment configuration has been completed
Deployment configuration file has been created.
Winter is coming…
Environment 'sdkjfsdkjfbdskfnasdfbsdkj' starting for deployment 'sdkjfsdkjfbdskfnasdfbsdkj'.
Waking up the minions.
Deployment 'sdkjfsdkjfbdskfnasdfbsdkj' of environment 'DEV' has failed
Please consult the CM and/or the Rendering Host logs using the CLI.
If the problem persists, contact customer support, and provide them the session tracing ID of 'sjdf0ebb2-1234-8989-as3e-465c15a66455'.

When we face any errors during the deployment the relevant logs can be found in deployment logs. But chances are there that not all the time the logs mentioned here will give the full picture about an actual issue. In those situations, environment logs provide far more trace.

While checking the logs, I found the below strace,

385148 21:27:33 ERROR Error in LicenseWatcher Exception: System.TypeInitializationException Message: The type initializer for 'Sitecore.SecurityModel.License.LicenseManager' threw an exception.
Source: Sitecore.Kernel at Sitecore.SecurityModel.License.LicenseWatcher.Created(String filePath)
Nested Exception Exception: System.Xml.XmlException
Message: Data at the root level is invalid. Line 1, position 1.
Source: System.Xml
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at Sitecore.Nexus.Licensing.NexusLicenseApi.get_Api()
at Sitecore.Nexus.Licensing.NexusLicenseApi.GetSnapShot(Guid instance)
at Sitecore.SecurityModel.License.LicenseManager.GetSnapshotData(Guid instance)
at Sitecore.SecurityModel.License.LicenseManager.UpdateSnapshot()
at Sitecore.SecurityModel.License.LicenseManager..cctor()

For this error, there is nothing you can do to fix other than reaching out to sitecore. This is because of an encoding issue in the license which only sitecore can update from their backend.

Rest of the issues are due to docker containers due to typical corporate networking components.

  • Docker and SOLR/ZooKeeper

                  XM Cloud – Local Docker Setup uses ZK with a single solr instance. Sometimes the solr container throws error – becoming unhealthy when it’s unable to connect to ZK.

In this case, you can configure SOLR straightaway without using ZK. Refer below blog posts,

1. Using Solr Standalone for your Local – Rock, Paper, Sitecore (rockpapersitecore.com)

2. Jeremy Davis – Strange Docker / Zookeeper errors (jermdavis.dev)

3. Miauw – a Sitecore blog: XMCloud SxaStarter local setup – solr-init issue (ggullentops.blogspot.com)

  • Docker unable to resolve hosts based on container name:

 By default, the XM Cloud containers – the apps be it solr or mssql they should be resolved based on the container name. Meaning, in the docker-compose.yml,

solr:
isolation: ${ISOLATION}
image: ${SITECORE_NONPRODUCTION_DOCKER_REGISTRY}nonproduction/solr:8.8.2-${EXTERNAL_IMAGE_TAG_SUFFIX}
ports:
- "8984:8983"
volumes:
- type: bind
source: .\solr-data
target: c:\data
environment:
SOLR_MODE: solrcloud
healthcheck:
test: ["CMD", "powershell", "-command", "try { $$statusCode = (iwr http://solr:8983/solr/admin/cores?action=STATUS -UseBasicParsing).StatusCode; if ($$statusCode -eq 200) { exit 0 } else { exit 1} } catch { exit 1 }"]
solr-init:
isolation: ${ISOLATION}
image: ${SITECORE_DOCKER_REGISTRY}sitecore-xmcloud-solr-init:${SITECORE_VERSION}
environment:
SITECORE_SOLR_CONNECTION_STRING: http://solr:8983/solr
SOLR_CORE_PREFIX_NAME: ${SOLR_CORE_PREFIX_NAME}
depends_on:
solr:
condition: service_healthy

solr is the container name. In solr-init container, the solr url is referred as http://solr:8983/solr. In non docker local setups solr will be referred as http://localhost:8983/solr. Referring them via container name is actually logical, because the IP address of these apps will be dynamically set each time they are spin up.

However, I have faced lot of times different containers not being able to resolve based on their hostnames.

2023-03-06 20:30:30 ManagedPoolThread #1 20:30:15 WARN  IsOnline: Test connection has failed with an exception. Type: 'SolrConnectionException', Message: 'The remote name could not be resolved: 'solr''

2023-03-05 11:12:01 Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Named Pipes Provider: Could not open a connection to SQL Server [53]. .
2023-03-05 11:12:01 Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login timeout expired.
2023-03-05 11:12:01 Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..

Although one is related to sol and another related to mssql and they both seem to provide a different error, fundamentally the cause for these two is same.

How?

You get the IP of SOLR container via, docker inspect “container-name” or if you use VS Code Docker extension, right click on a container and select inspect. This will give you a json of details of which one is IP Address. In place of the container name use this IP Name and rerun the up.ps1 if your issue is in fact because of docker not able to resolve host by the containers name this issue will now be resolved. However, this is not recommended as the IP will be changed the next time when you docker-compose down and docker-compose up.

In case of MSSQL, you can connect to the container mssql instance from host SSMS by using the localhost, portnumber and sql server authentication via sa account. The required port number/ password details are available in the .env file

These issues are mainly due to firewalls/proxies and VPNs. There is no one direct fix for this as this may vary from client network to client network. You can try disconnecting from VPNs. However, you can try troubleshooting based on the below,

  • TRY removing the default switch in the docker. Because anyways the XMC docker will create a separate switch for it’s list of containers.
  • See if the containers are connected to the XMC Docker Network (sxastarter_default)
    1. docker network ls
    2. docker network inspect "Network_Name"
    3. Connect/Disconnect,
      1. docker network connect "Network_Name" "Container_Name"
      2. docker network disconnect "Network_Name" "Container_Name"
  • Try pinging the target container. -> ping "container name"
  • Check if the target port is open in the corresponding container via it’s PowerShell, Instead of IP you should use the container name.

PS C:\inetpub\wwwroot> Test-NetConnection -ComputerName 172.30.148.232 -Port 8983
ComputerName : 172.30.148.232
RemoteAddress : 172.30.148.232
RemotePort : 8983
InterfaceAlias : Ethernet
SourceAddress : 172.30.157.226
TcpTestSucceeded : True

  • Try changing the network adopter priority, based on the article Blogs / Perficient / Sitecore Docker Troubleshooting
  • If none of the above works, as crazy as I may sound, try bringing down the entire containers, networks using docker compose down/prune and bring it up. I don’t know what difference that would actually make but this helped me overcome a couple of issues. (Yes..it is at this moment logic has left the world)

A Few Good to Know before you start your local setup:

  • The two init containers – solr-init and mssql-init are used to initialize your actual solr/mssql server with sitecore indexes/sitecore databases. So for these containers to be up, the relevant containers – solr/mssql should be up and healthy and they will be referred in the init containers via connection strings. Also, once the solr/mssql containers are initialized these two containers will be exited.
  • Most of us will be using a low disk space C drive….Okay if you are like me who had to use a low disk space C drive, we can actually map the docker data root to D drive via the daemon file.
  • Also, try to include the google dns 8.8.8.8. Sometimes the resources to be downloaded during docker compose up may be blocked.
  • Make sure the IIS is stopped. Sometimes if you are setting up local for multiple days chances are there that after starting you machine again, IIS will be turned on automatically. Although IIS Server stop is not mentioned anywhere and only the IIS apps needs to be stopped, I faced an issue which resolved only after I stopped IIS.

Sitecore – Experience Manager Cloud – Introduction

Got my first hands on Sitecore Experience Manager Cloud aka XMCloud recently and this blog series of blog is intended to share my findings and learnings.

As XM Cloud is still a least explored product among the sitecore developers, I thought I should start from the basic. Create a series with 3-4 articles.

This series is intended for developers and technical users who wants to get a basic understanding on XMC. This is series is not a sales pitch or a rave attempt to woo customers/business users.

Sitecore Experience Manager Cloud:

                XM Cloud is Sitecore’s latest SaaS offering for developing enterprise level digital web applications based on headless CMS. In simple terms, instead of installing Sitecore XM/XP in our server and developing websites, the equivalent XM/XP will be centrally hosted and can be accessed based on subscription and Content will be delivered  to our application via Edge API.

This means that just like how we can login into Azure via portal.azure.com and consume Azure Products similarly we can now login to https://portal.sitecorecloud.io/ and consume XM Cloud products and services.

There are several benefits (and changes) by this SaaS approach in a sitecore application’s development and maintenance lifecycle.

  • No infrastructure setup is required from our end. We don’t need to install sitecore in DEV/QA/UAT and of course PROD. All we need is to push some buttons in XM Cloud to create projects and specify the environment needs for each projects.
  • As the sitecore instance is not installed and maintained in our servers and that we are consuming them as a service, we don’t need spend much effort on upgrade activities. Which means you can sleep with X Version and wake up to a Y version.Yes I’m over hyping it and that’s not the case (for)now. But XM Cloud is the closest we can get to what I meant. Although the zero code/zero effort needed from our end during upgrade is not an official statement, I assume we might require some work from our end, but that will be way less than how we are doing our upgrades now. (Some of the info mentioned here may be wrong and misleading. I have updated it please check the last)
  • Scaling and Availability – Once again, because of SaaS and sitecore owning the infra related components, scale up and down are easy and can be done on demand. * (Updated please check the last)

* As this uses Edge to provide contents to your static site hosting there may be some additional work needed from that end.

Once, you login into XMC, you will be redirected to your organization’s home page

This page has all the modules or at least redirection to all the modules related to managing your XM Cloud instance. XMC classifies each instance Organization level. Organization here implies Customer or Implementation Partners. Each organization can have several XM Cloud projects. This limit is determined by your license. Each projects can have multiple environments. (PROD/Non-PROD(DEV/UAT/QA)) based on your license again. Not sure how the prices are set, but sitecore mentions it as pay per use.

Admin page provides details about the number of users in your organization and their roles. You can invite new members to you XMC from your organization by inviting them. While inviting new users, you can specify the access for them. Admin or User. Admin has full access to all your org. projects. And with User level you can limit the access to a particular project/app.

XM Cloud Deploy

You can create a new project for your organization via Manage my projects-> Which will redirect to https://deploy.sitecorecloud.io/. This is the platform used to create/manage/deploy sitecore XMC projects. This is the devops feature which XM Cloud provides. While creating a new environment, you can specify the repository from where you can deploy your headless sitecore code to XMCloud environment. By default XMC provides UI for GitHub repo. However, you can deploy your project from any git repo(AzureGit,BitBucket) using Sitecore CLI -> Cloud plugin/deployment command or via API. If there is no Headless cloud repo you can make use of sitecore’s sitecorelabs/xmcloud-foundation-head (github.com) repo. While creating a project and environment you can authenticate using git credentials and XMC creates a repo based on the foundation head and maps that to the created environment.

One of the key feature of XMC Deploy is that it can trigger a deployment when a commit is done to a target branch.

XM Cloud Pages:

Apart from the usual Sitecore modules – The Content Editor/PowerShell/Access Management etc. which we already have in XM/XP Sitecore,

There are 3 new modules, Pages, Components and Explorer. Of these, Pages resemble Horizon, but it provides far more features when compared to Horizon.

Components are something that’s entirely new to Sitecore XM/XP landscape. It’s unlike any other existing Sitecore modules. It allows us to create a component in XM Cloud from various external data sources (exposed via GraphQL, REST API). You can setup a data source, configure the end points and map their response to a component ultimately adding the component to a page. How cool is that? More about this in coming days.

First Impressions:

  • XM Cloud is the final piece that is needed for the Sitecore’s Composable future.
  • Has lot’s of OOTB features that’s gonna save lots of time in bringing a project to live there by drastically reducing the time to market.
  • It help’s directing efforts into actually creating a component and sites instead of spending efforts/time in setting up/managing infra. In a project cycle.
  • Apart from the new modules and their features mentioned above, all the remaining modules of existing sitecore is included and available in XM Cloud. However, Sitecore + MVC now belongs to a museum. XM Cloud doesn’t support MVC components and there is actually a re-write required.
    • XM Cloud Deploy, Components are truly a game changer.
  • As far as migrating contents from existing Sitecore XM/XP to XM Cloud, Sitecore CLI’s new cloud plugin comes in to play. (More on this in upcoming days)

Okay all that was discussed so far was about the PROD/Non-PROD environment. What about local?

Sitecore XM Cloud – Local Development setup: (Based on xmcloud-foundation-head)

  1. Setting up sitecore XM Cloud environment in local for development is straight forward. You have the repo created in your GitHub, while creating an instance.
  2. Before that the pre req. include
    1. Powershell
    2. Docker – Hyper V enabled.
    3. Node.js LTS
    4. Dotnet 6
    5. .NET Framework 4.8
    6. And most importantly license.
  1. Clone the repo. Powershell(Admin)-> in the cloned repo folder ->  run init.ps1 providing the path to license and the sitecore admin password.
  2. And then up.ps1

However as simple as it seems, when I setup first time there were a lot of issues. Mostly between Firewalls, VPNs, Proxies and Docker.

I am planning to share the list of issues I faced and how I solved/identified work around in my next article.

*Thanks to @guitarrich,

  1. Version Upgrade: You can in fact actually go to SLEEP with XM Cloud Version X and WAKE UP to Version Y. Sitecore upgrades will be released in a way they don’t break our code or prevent our code from building. In case if there is any failure while applying the upgrade and the build fails, the update would not be deployed, and you would be notified for a build failure.
  2. Scaling Up and Down: XM Cloud provides the content via Edge to our Headless Application and scaling of the that part of your web application is completely/only in our hands. XM Cloud can be scaled for Content Authors and editors/storage space needed based on license.

Sitecore – Ways to configure a list field’s source

So, I came across a situation where I had to provide only selected options for a list field type(Multilist/Droplist etc) based on some conditions.

Although this was not a hard requirement and mere mapping of a parent item was acceptable, I’m more of a fan of “build code that is designed for Operations” as I have had fair share of experience in someone always misconfiguring stuffs.

Usually, I hit sitecore queries for such requirements. When we need items that are it’s ancestors or items that matches a particular template,  or a child items that match a particular pattern etc

query:./ancestor::*

But it my case, the requirement was a bit difficult. I wanted to set the datasource for a droplist based on a selection made it it’s parent item’s multilist field. With Sitecore Query, I was able to traverse upto the parent item only (query:../). Via query, we cannot access an item’s field.

So explored other options,

IDataSource:

While creating a template you would have configured source item for a list type.

We can create our custom datasource by creating a class that implements Sitecore.Buckets.FieldTypes.IDataSource. This interface has one interface method Item[] ListQuery(Item item). This method returns an array of item that acts as a datasource for the list type fields.

using Sitecore.Buckets.FieldTypes;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;

namespace Mark9.Foundation.SitecoreExtension.FieldDataSources
{
    /// <summary>
    /// Parent item's selected destination category
    /// </summary>
    public class ParentItemDestinationCategory : IDataSource
    {
        public Item[] ListQuery(Item item)
        {
            var destinationCategory = (MultilistField)item.Parent?.Fields["Destination Category"];
            if (destinationCategory!=null) {
                return destinationCategory.GetItems();
            }
            return new Item[0]; //Return an empty item array
        }
    }
}

You can map this as a data source by adding the below to the source field.

code:Mark9.Foundation.SitecoreExtension.FieldDataSources.ParentItemDestinationCategory,Mark9.Foundation.SitecoreExtension

But this would require a code deployment and if we were to make any change to the requirement it would take more time. There is another way where we can configure custom datasource for list data types using sitecore PowerShell.

We can map this script as a datasource appending it with script:

script:/sitecore/system/Modules/PowerShell/Script Library/Custom Scripts/GetSelectedCategory

Sitecore – Item as a Resource – Deep Dive -1 – IaaR Plugin

Last year, I wrote an article about Sitecore IaaR when I first came across that concept. This is a continuation to that article.

So…a quick recap. Starting from Sitecore 10.1,  default sitecore items are stored in resource files (items.{database}.dat) serialized via Google ProtoBuff. This helps mainly with ease of Sitecore upgrade/Container based deployment.

Sitecore CLI – IaaR plugin

  • Sitecore has provided options to create custom resource files for project specific needs.
  • This can be achieved via Item as a Resource Plugin.

Sitecore.DevEx.Extensibility.ResourcePackage v.5.1.25

  • itemres command – The resource plugin has itemres command. This command creates the resource file based on the settings from *.module.json file.

Note: This creates the resource file from the database, by that I mean, irrespective of the state of the items in the /serialization/*yml.

  • dotnet sitecore itemres create -o {ResourceFileName}

The resource files will be named as items.master.{ResourceFileName}.dat

  • The created resource file should be placed in  webroot/App_Data/items/master
  • Need to create a copy of this file and rename it for web database and place it under

webroot/App_Data/items/web/

Post Steps:

  • For the changes to reflect – we have to restart the application
  • Now that the items are created as resource file and are moved to the target folders, I would recommend cleaning up these items in the database.
  • dotnet sitecore itemres cleanup – this cleanup command removes the items that present in the resource file for all the 3 databases.

Few Points to be noted:

  • Sitecore shows these items in the content tree from the resource files.
  • When you make a change to any of the resource item, sitecore includes the changes and moves the item to database.
  • For all further use, the item read/write operation takes place from database.
  • You cannot delete the resource file items individually from the content tree.
  • This means that while creating resource files for custom items, the item can only be templates/renderings and configuration items but no content items – pages etc. and of course resource file are not meant for page like content items.
  • Also, this means that, if any resource items has to be removed them it needs to be removed from the configuration (module.json) and then needs the updated resource file has to be deployed.

Sitecore Content Hub – Import/Export assets via Excel

All the assets present in our sandbox will be present in the Assets page. (Unless any rules are set)

Now, remember in our prev. post we would have added few assets. But these assets are not listed in the assets page. This is because these assets are not in the final stage of the workflow. i.e., these assets are not reviewed.

These assets are present in Create page. Now, let’s first send these assets for review.

Once submitted these assets wont be present in Create page. They will be available in review page. You can approve all these images. Once these images are approved they’ll be available in Assets page.

Now let’s export all these four images. To Export these images first let’s enable the Export to Excel option.

This option will usually be present in the selection menu in Assets page. If this option is not enabled, we can enable it using pages section in manage/admin page.

Select Asset page, In Header Zone(Right) edit the selection component, In General settings tab, check the Enable export to Excel button.

P.S: From the operations tab, you can additional operations to be included upon selection.

Now after saving the changes, let’s head back to assets page and select all the assets and click on Export to Excel to export these assets details to excel.

Importing assets from Excel:

First let’s see the basic requirements/structure of the excel sheet that needs to be fed for import process.

  1. The Sheet name should match the definition i.e., M.Asset in this case.
  2. The Sheet’s Column name must match the schema’s member’s identifier.
  3. The Sheet must contain all the required schema member’s value for an asset to be imported. If this is not configured properly, you will get, “No self-relation columns were found in sheet M.Asset” error and the import job will be failed.

In the create page, if the import excel option is not available, just like before we can go to pages module in admin/manage page and select the creation component in the Header Zone right and edit them to include Import Excel.

Now, let’s upload the excel sheet and import the asset.

Once upload is successful, you can check the status of the import job from the Background Processes page. You can access this page by clicking Administrator Icon present in top right and selecting the background processes option.

Once the import job is successful, you can see the image in the create page.

While uploading if you include the FinalLifeCycleStatusToAsset field and include the appropriate values then these assets while importing itself will directly be placed in the assets page. Please note that while giving the value for FinalLifeCycleStatusToAsset column, you must mention the identifier of the value and not just the value’s label.

Eg. If you want the asset’s lifecyclestatus to be Approved you must mention the value as M.Final.LifeCycle.Status.Approved. The same is applicable for any of the taxonomy/relation member of the schema. The column name/imported value must be their identifier. If the member is a property and it’s type is option list the same applies.

Sitecore Content Hub – Themes and Pages

Your Sitecore Content Hub themes can be updated using the Themes section in the manage/admin page.

Sitecore by default comes with one theme which you cannot edit. But you can create your custom theme to match your overall branding UI Theme and can add logos, favicons etc. You can even add your CSS.

Simply via theme you can setup the look and feel. Fonts, Font Colors, etc

Once you created to see them applied, you have to enable the theme.

Pages:

Every presentation component you see in your Sitecore Content Hub sandbox can be managed from the pages section in the manage/admin page.

You create a  new page from here using the +Page button based on a page type.

Basically there are three page type.

Blank Page: You can create a blank page with a layout and can add components to that page.

Detailed Page: You can create a detailed page for a definition. For Eg: Like the default OOTB Assets page for M.Asset definition.

From Template: Based on a template you can create a new page. For enabling an existing page to be a template, you need to check the Is template field in the page’s Info tab.

I have already enabled the default HomePage as template and created custom Home Page based on that template.

Now, let’s see this page’s configuration from sandbox side.

Note here the all the components configured under Main Zone.

In the First Row, you can see the HTML Component – Intro Text. Similarly you can add any of the preconfigured components.

You can set the columns for each row from the settings modal.

We will see how we can include changes to existing pages like adding new options, removing any existing options etc in the next post.

Introduction to Sitecore Content Hub – Digital Asset Management

A little bit of Preface:

I’m very late to write about this,  as Sitecore has acquired Stylelabs around 2018 and have launched Sitecore Content Hub approximately in 2019. In fact as I write this article Sitecore Content Hub 4 (4.0.27) is the latest version.

Was planning to explore this product a long time. But unlike traditional Sitecore XP or XM this cannot be installed on an individual machine and explored as it’s a SaaS offering. So to get my hands on Sitecore Content Hub was a bit difficult.

Finally, after years managed to get access to Sitecore Content Hub and tried to share my experience over this blog.

There must be several articles out there that may provide more detailed info. But if you are getting started with Content Hub or would like to know the fundamentals of this product, this post might be useful.

So Sitecore Content Hub?

Sitecore’s first SaaS based offering. Hub usually means centre of an activity, network. Sitecore Content Hub is a collection of different modules like Digital Asset Management (DAM), Content Marketing Platform (CMP), Product Content Management (PCM), Marketing Resource Management (MRM).

Will write more about the other modules in the future. For today we’ll start with DAM – Digital Asset Management.

Sitecore Content Hub DAM

Straight forward title – Digital Asset denotes images, videos, files and other rich medias. Management denotes a platform to manage all these digital assets.

Like me if you are coming from a traditional CMS background, where we use a Media Library to store images and files, you may wonder why you need a DAM when you can store the images in Sitecore Media Library.  Trust me after knowing about Sitecore Content Hub DAM, it felt funny to me for having thought in that angle.

To put it in a nut shell, say you are a big global brand and you have multiple websites – country wise and you have to manage these digital assets for all of their web applications and also let’s throw in some upstream and downstream systems ERP, E-Commerce, marketing platforms and analytics reporting systems and to top it off, you have standard rules or requirements on where they can be used and who can be allowed to access those assets?

The Media Library in any CMS is designed to be used around those sites and those site’s webpages where they are intended to use. Not any where beyond that.

DAM provides solutions to all these complex requirements.

You can get analytical report asset level. You can tag/categorize assets.

Okay…enough with the introduction, let’s get started with the Sitecore Content Hub – DAM

Once you login to your Sitecore Content Hub sandbox this is the homepage you will be landed to. Ignore the menus and structures for now, let skip straight to the Settings gear on the top right.

This is the Content Hub admin page or manage page which contains all the modules that will be used to manage your Content Hub sandbox.

In order to understand the different and actual components of Sitecore Content Hub DAM, there are few basic terminologies that you should be aware.

Schema:

Schema page will list all the schemas present in your instance. Both default and custom. Schema is like the fundamental building block of Content Hub. All the assets that you are creating, by default are based on M.Asset schema. The assets created are the entities.

A Schema has several Member Groups (Overview/General/Options etc). Each Member group has Members. Each Member can be one of the three types (Property, Relation and Taxonomy).

Property: Common data types like string, bool, integer, Option list, JSON.

Relation: A link to another entity.

Taxonomy: Taxonomies comes handy while organizing/tagging/searching assets. They can be added as filters. Say, for an asset, it’s media can be a taxonomy with taxonomy details being audio, video, images etc. Taxonomy details can have hierarchy.

Show Entities lists all the entities based on the schema M.Asset. Let’s upload some images.

To create images, you can go to Create page view Create Menu in the Main Navigation. Then Add. For time being we can add them via Upload Files.

If all the required conditions are met then these files will be uploaded successfully. Required Conditions????

Let’s get back to Schema and check the Member Group Overview->Title->Edit->Required tab.

So for each entities created based on the M.Asset schema, Title is a required property failing to pass that attribute during creation will lead to error.

Similarly, we can create custom member groups and custom members for a schema and set such required conditions. Say, we can add a meta data member group and add meta data properties that needs to be compulsorily filled while creating an asset.

Now that the images we created are added in Content Hub, let’s check the entities for M.Asset schema via show entities.

In this Asset Detail page, you can see the different Member Groups -> Overview, Image Analysis and their Members -> Filename, Title etc getting displayed. So to put it in a relative term, Member Groups are similar to the Template Sections and Members are similar to individual fields in a Sitecore Template.

In a way schemas are like the templates and Entities are it’s item.

So far we got to know about Schema, Entity, Taxonomy and assets.

Now let’s go after the presentation components of Content Hub sandbox – Themes and Pages.

Sitecore – Headless – API Key – Throttle Strategy

Preface:

I planned to write a fresh series of articles under the title – “Sitecore Reboot”.  In continuation with my “Sitecore – Yesterday…Today and Tomorrow” post, how,  with  the lastly released Sitecore XM Cloud, sitecore has gone all SaaS and related to that.

This article was lined up as second one on that series. But unfortunately I am not able to finish working on the first part yet, so instead of waiting anymore, thought of sharing this one first.

Sitecore API Key:

So most of us know that in order access Sitecore  GraphQL or Sitecore Layout Service we need an API Key (SSC API Key authentication). We’ll be creating that API Key under /sitecore/system/Settings/Services/API Keys/ based on the template /sitecore/templates/System/Services/API Key.

This API Key template has the following fields,

CORS Origin: Here you can specify the origins other than this application’s own origin, whose request can be allowed to be processed.

Allowed Controllers: Specify the controllers that can be accessed using this API Key. i.e., LayoutServiceController, GraphQLController etc

Impersonation Users: For anonymous users, you can specify the user here usually extranet/anonymous. This will be used to determine the security context of the JSS App to Sitecore content.

Simple and straight forward right?. That’s what I thought too until I saw the last field – Throttle Strategy. This was kind a new to me.(Although I’m aware the logic behind it, I wasn’t aware of this terminology).

In the sitecore documentation related to API Key – Create a Sitecore API key I was not able to find any content related to this…… NICE.

This stirred my curiosity and I checked the templates and started to browse about Throttle Strategy in general.

So what is Throttling in terms of Web API Development?

Throttling is the means by which you can set how your API can serve the incoming requests. By this I mean, one can put some rules for serving the request. One simple such rule is – Number of requests that can served per time unit. When a request even though it’s legitimate by all other means can be stopped from processing using such throttle strategy.

Okay, why would I even need that?

  1. It offers more security. The Sitecore Layout Service or GraphQL end points are all means to connect with the Sitecore backend. Including throttle strategy includes an extra layer of protection.
  2. A throttling rule can be applied based on IP Location. Some days ago, I read a case study related to Amazon India where in a particular region, some regional sellers were making more orders and cancelling them before delivery (for obvious reasons) and Amazon has blacklisted that region temporarily. Throttle Strategy can be set to limit the number of requests per time unit from a region. (It may sound paranoid or doesn’t make any sense for some. I’m just saying such measures if needed can be done by throttling strategy)
  3. Finally, it can improve the performance by preventing the excess use. In cases like Auth0 or any other such Cloud based Identity Management, the API requests are monetized. Meaning like for a given time frame this much requests are free and if there are more than allowed count, they will be charged per request.

Let’s get back to Sitecore, Sitecore provides two OOTB option to specify throttling strategy.

Sliding Window Strategy: Specify the number of requests that can be served per time unit. Any request beyond that number will not be processed.

Composite Strategy: You can configure multiple strategy into a single composite strategy and can set them to your API key

And just like any other feature in Sitecore, you can also create your own custom throttle strategy following this link –  Create a new request throttling strategy (sitecore.com)

So, you have created the API Keys, have set the throttle strategy is that it?

We have to enable the throttle strategy by setting Sitecore.Services.IsThrottleEnabled key to true in Sitecore.Services.Client.config,

Now, I could have just believed sitecore and moved on to my next activity. But being the weirdo, I am, I wanted to test myself and see the results and for that I wrote a dummy console application.

When the throttle strategy is set to 1 Request per Second Sliding Window Throttle Strategy.

Only the first request is served and the remaining requests are not processed and are give TooManyRequests StatusCode in the response.

When the throttle strategy is set to 10 requests per 30 second

Here you can see the first 10 requests sent at one second interval each getting served while the next set of requests are not processed and after 30 seconds the next request is processed. By the time this happens for the next 30 seconds already 10 requests are processed so again requests will be responded with TooManyRequests Status.

Using the Composite Strategy, you can combine any such strategies.

The same can be tested via browser, but complicated scenarios that I intended to test can be better done with code. Hence that dummy console application. However, when tested in browser for a simple throttle strategy if it fails the condition the response you get is below.

Sitecore – Dependency Injection

Dependency Injection was always a tricky concept and hard to understand for me when I started my career.(Well, in fact even in college days this was the chapter that I left on optional.)

Later, after working on .NET web applications and I understood the basics of Dependency Injection, But I still had some gaps. So, when I got a chance to explore more about this concept, I jumped right in and thus sharing my experience via this blog.

.NET Web Applications are based on C# which is in turn based on OOP. So this means classes and objects…..lots of classes and objects. These Classes and Objects depend on one another. With an increase in time the number of classes and objects will increase, causing complexity to increase if not implemented properly. Also with increasing complexity the maintenance will be difficult.

Normally, we will have a interface and a service class that implements that interface a constructor that has this service class as attribute. Like below,

Application Execution wise there’s no big problem with the above code. It will execute fine. But you see here, there’s a tight coupling created. Meaning objects creating another objects on which they depend on. With the increase in the lifetime of an application this kind of hard coupling is gonna increase.

Dependency Injection addresses this issue. DI states that components – objects shouldn’t create objects they depend on, instead they should be passed to them. Thereby reducing the tight coupling, increasing maintainability etc. There are multiple ways to do this.

  • Constructor Injection
  • Property/Setter Injection
  • Method Injection

The most commonly used  approach is Constructor Injection, where we pass the dependencies via constructor thereby allowing them to be used anywhere within the class.

Sitecore Default DI is Microsoft DI. So, we need a ServiceConfigurator where we can register the dependencies which can be passed on to the controller.

When we inject a dependency there are ways in which their lifetime can be set.

AddTransient – The services are created each time they’re requested.

AddScoped –  The services are created once per client request.

AddSingleton – The services are created for the first time they are requested and then every subsequent request will use the same.

We need to register this Service Configurator via config file like below.

We can also register a service from config directly . We can check the dependency registration – service configurations via,

/sitecore/admin/showservicesconfig.aspx

So it may seem we have done everything required. Let’s give it a spin.

We have done almost everything. Created Interface->Service Class->Controller->Registered the dependencies in Service Configurator->Passed the dependencies via constructor controller. But still we get the above error.

This is because for the controller the dependencies were not getting passed. Which means we still have one action pending. Which is registering the controllers. We need to register every controller that consumes the dependencies.

We can also get the dependencies using Service Locator. If you don’t have the option of passing the dependencies via Constructor Injection then getting the dependencies via Service Locator is the other option.

Regarding Controller registration, instead of doing them individually, thanks to Kam Figy’s code they can be registered all together based on the assembly. FYI

Now, we can register new services that will be developed during the lifetime of the web application in the service configurator and use them in the controller. This improves code maintenance and reduces tight coupling. This also enables us to implement better unit testing. Say we have Rest API related implementation. When we write unit test methods they can’t call actual API. In such cases mock response needs to be used. When can have some config keys where we can decide when to use actual implementation and when mock implementation. And the actual or mock implementation can be passed as a dependency via Service Configurator.

Sitecore – Analytics Report Query

Last week one of my friend asked me whether I have worked on something that kinda allows us to show Sitecore Analytics data like Top 5 Visited pages of a website in a 404 error page…Something like page you searched for is not found…Interested in checking out these top visited pages….(Probably some content with better English)

Although I haven’t worked on such requirement but the idea of displaying some analytics data in a webpage of  the website thereby providing a better user experience caught my attention.

So I explored it further and thought I would share about the steps involved.. in this article.

Sitecore has a reporting DB that has details about these data. The reporting database contains aggregated data from the xDB collection database. In Experience Analytics module,  were you see the Number of Visits, Top Page Entry/Exit etc are presented based on the data in this DB.

This reporting db has a table Fact_PageViews. Fact table is a data warehousing term used to describe tables that contain measurements and metrics. In a fact table foreign keys allow joins to be made with dimension tables.

After exploring this DB/table for few mins wrote a query that solves our requirement.

So, now all we have to do is create some logic that runs this query when needed and provides the Item IDs. Based on this Item ID, we will be able to get the page details like page name and URL which can be presented in the rendering.

After some browsing I came across Sitecore Report Query

Sitecore has this Report Query template that allows you to specify the datasource (the DB) and the query that needs to be executed.

So, create an item based on this template and include the necessary values. (Datasource – reporting and our query)

From code prespective,

Create a class that is based on ItemBasedReportingQuery. Make use of the item ID of the report query item we just created and pass them in the constructor (base)

Implement the Execute method and include our logic there. After the query is executed, the results are available in datatable format, from which we can convert them to our custom format.(PageandViewCount).

Create a helper class/method that executes this query.

Finally, based on the item id we can get the item. Based on the item we can get the page name/page url. Create a corresponding rendering and add it to the required page.

There is also another way to execute sitecore query, using the reporting API straight away without using the report query item. But here you need to hard code the query or fetch it from some constants.

Design a site like this with WordPress.com
Get started