Skip to main content

Custom Fields in Sitecore (Custom DropLink, DropTree, MultiList, TreeList and Required Field Validator)

Custom Fields in Sitecore Just thought to share few of the custom Sitecore fields that I have created for one of the sample project. This may help the community memebers to easily incorporate them into their project if they need any of them. Here are few.
1. Custom DropLink
  
using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomDropLink : Sitecore.Shell.Applications.ContentEditor.LookupEx
    {
        protected override void DoRender(System.Web.UI.HtmlTextWriter output)
        {
            this.ExcludeItems();
            base.DoRender(output);
        }

        private void ExcludeItems()
        {
            Item item = Sitecore.Context.ContentDatabase.GetItem(base.ItemID);
            var LinkedField= Sitecore.StringUtil.ExtractParameter("ParentField", this.Source);
            var fieldvalue = item.Fields[LinkedField].Value;
            NameValueCollection parameter = HttpUtility.ParseQueryString(Source);
            parameter["datasource"] = fieldvalue;
            this.Source = HttpUtility.UrlDecode(parameter.ToString());           
        }
    }
}
  
  

2. Custom DropLink
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Extensions.Constants;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomDropTree : Tree
    {
        private bool hasValidSource;
        public CustomDropTree()
        {
            Class = base.Class + " ftFieldTreeExtended";
            base.Activation = true;
        }
        public new string Source { get; set; }
        public static bool HasSourceChanged = false;
        /// 
        /// Validate the valid source item, if not been selected, prompt user with a message.
        /// 
        /// HtmlTextWriter
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                this.Attributes["onchange"] = "HideDependentFields(this, true)";
                base.DoRender(output);
                return;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.ServerProperties["Value"] = this.ServerProperties["Value"];
        }
        /// 
        /// OnLoad event.  Override the OnLoad event to inject our DataSourceField 
        /// when the selected value of the data source field changes.
        /// 
        /// 
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                base.Source = this.Source;
                var fieldValue = ConfigurationManager.AppSettings["ContentItemGUID"];
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        base.Source = String.Format("{0}&DataSource={1}", Source, sourceItem.Paths.Path);
                        this.Value = SanitizeValues(sourceItem, Value);
                    }
                    hasValidSource = true;
                    SetModified();
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                        //TreeList.SetModified();
                    }
                    base.SetViewStateString("Value", str);
                }
            }

            base.OnLoad(e);
        }
        /// 
        /// If they are not children of the item in DataSourceField, remove GUIDs from a list of selected values 
        /// 
        /// Selected Item in field specified by DataSourceField
        /// Current value of the TreeList field
        /// List of values that are descendents of TreeList fields source.
        private string SanitizeValues(Item sourceItem, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]));
                if (item.Axes.IsDescendantOf(sourceItem))
                    validItems.Add(item);
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
		
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
       
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        /// 
        /// Gets 'DataSource' value from Source query parameters
        /// 
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }

        /// 
        /// Returns the value of a field from Data Source.
        /// 
        /// fieldName is the field being used as a Data Source
        /// Value of the Data Source.
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;
            Item item = CurrentItem();
            if (item == null) return String.Empty;
            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;
            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;
            return fieldValue;
        }

        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID));
        }
		
        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        /// 
        /// Takes string of guid or a path and returns Item set in DataSourceField  
        /// 
        /// string of guid path or Item found in the field specified by DataSourceField
        /// Item
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");

            if (db == null) return null;

            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource));

            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource);

            return null;
        }
		
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }

        private string GetTypeDatasource()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string sourceGuid = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        return sourceGuid;
                                    }
                                }
                            }
                        }                   
                    }
                }
            }
            return string.Empty;
        }
    }
}
 
 

3. Custom MultiList
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Web.Extensions.Constants;
using System.Web;
using System.Text;
using Sitecore.Globalization;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomMultiList : MultilistEx
    {
        private bool hasValidSource;
        public CustomMultiList()
        {
            // css class
            Class = base.Class + " ftFieldTreeListExtended";
            base.Activation = true;
        }
        // source values
        public string Source { get; set; }
        public static bool HasSourceChanged = false;
        /// 
        /// Validate the valid source item, if not been selected, prompt user with a message.
        /// 
        /// HtmlTextWriter
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                base.DoRender(output);
                return;
            }
        }
        /// 
        /// OnLoad event.  Override the OnLoad event to inject our DataSourceField 
        /// when the selected value of the data source field changes.
        /// 
        /// 
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            Item parentItem = null;
            string fundComponentName = string.Empty;

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                var fieldValue = ConfigurationManager.AppSettings[CMSConstants.ComponentItemGUID];
                var db = GetDatabase();
                var includeTemplates = HttpUtility.HtmlDecode(GetTypeIncludeTemplates());
                Sitecore.Data.Items.Item[] labelItems = null;
                Sitecore.Data.Fields.MultilistField components = null;
                parentItem = CurrentItem().Parent;
                if (labelItems != null)
                {
                    foreach (Item labelItem in labelItems)
                    {
                        components = (Sitecore.Data.Fields.MultilistField)labelItem.Fields["ComponentName"];
                        if (components != null && components.List != null && parentItem != null && parentItem.Fields["Content Type"] != null && !string.IsNullOrEmpty(parentItem.Fields["Content Type"].Value) && components.List.ToString().Contains(parentItem.Fields["Content Type"].Value))
                        {
                            sbItemId.Append("@@id='" + labelItem.ID + "'").Append(" or ");
                        }
                    }
                }
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        if (sbItemId.Length > 80)
                            base.Source = sbItemId.ToString().Remove(sbItemId.Length - 4, 4) + "]";
                        else
                            base.Source = string.Empty;
                        base.Value = SanitizeValues(sourceItem, parentItem, labelItems, Value);
                    }
                    hasValidSource = true;
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                    }
                    base.SetViewStateString("Value", str);
                }
            }
            base.OnLoad(e);
        }

        /// 
       /// If they are not children of the item in DataSourceField, remove GUIDs from a list of selected values
        /// 
        private string SanitizeValues(Item sourceItem, Item parentItem, Item[] labelItems, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            Sitecore.Data.Fields.MultilistField components = null;
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]), Language.Parse(ItemLanguage));
                if (item != null && item.Axes.IsDescendantOf(sourceItem))
                {
                    foreach (Item labelItem in labelItems)
                    {
                        components = (Sitecore.Data.Fields.MultilistField)labelItem.Fields["ComponentName"];
                        if (components != null && labelItem != null && item != null && labelItem.ID.ToString() == item.ID.ToString() && components.List != null && parentItem != null && parentItem.Fields["Content Type"] != null && !string.IsNullOrEmpty(parentItem.Fields["Content Type"].Value) && components.List.ToString().Contains(parentItem.Fields["Content Type"].Value))
                        {
                            validItems.Add(item);
                        }
                    }
                }
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
        /// 
        /// Gets 'DataSourceField' from Source query parameters
        /// 
        /// Field name used for DataSourceField
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        /// 
        /// Gets 'DataSource' value from Source query parameters
        /// 
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }
        /// 
        /// Returns the value of a field we're using as a Data Source.
        /// 
        /// fieldName is the field being used as a Data Source
        /// Value of the Data Source.
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;

            Item item = CurrentItem();
            if (item == null) return String.Empty;

            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;

            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;

            return fieldValue;
        }
        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID), Language.Parse(ItemLanguage));
        }
        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        /// 
        /// Returns Item set in DataSourceField.  Takes string-guid or string-path.
        /// 
        /// string-guid or string-path or Item found in the field specified by DataSourceField
        /// Item
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");
            if (db == null) return null;
            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource),Language.Parse(ItemLanguage));
            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource, Language.Parse(ItemLanguage));
            return null;
        }
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }
        /// 
        /// Reads customdatasource from template. 
        /// From customdatasource, finds appsettingkey based on type selected from parent of current item
        /// Returns value of appsettingkey
        ///         
        /// string
        private string GetTypeIncludeTemplates()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string appSettingKey = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[appSettingKey]))
                                            return ConfigurationManager.AppSettings[appSettingKey];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return string.Empty;
        }
    }
}
  
 
4. Custom TreeList
  
using System;
using System.Collections.Generic;
using System.Web.UI;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using System.Linq;
using System.Configuration;
using SitecoreCustom.Web.Extensions.Constants;
using System.Web;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    public class CustomTreeList : TreeList
    {
        private bool hasValidSource;
        public CustomTreeList()
        {
            Class = base.Class + " ftFieldTreeListExtended";
            base.Activation = true;
        }
        public new string Source { get; set; }
        public static bool HasSourceChanged = false;
        protected override void DoRender(HtmlTextWriter output)
        {
            if (hasValidSource)
            {
                base.DoRender(output);
                return;
            }
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.ServerProperties["Value"] = this.ServerProperties["Value"];
        }
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                base.Source = this.Source;
                var fieldValue = ConfigurationManager.AppSettings["ContentItemGUID"];
                var includeTemplates = HttpUtility.HtmlDecode(GetTypeIncludeTemplates());
                if (IsPathOrGuid(fieldValue) && !SourceContainsDataSource())
                {
                    var sourceItem = ResolveItem(fieldValue);
                    if (sourceItem != null)
                    {
                        base.Source = String.Format("{0}&DataSource={1}&{2}", Source, sourceItem.Paths.Path,includeTemplates);
                        this.Value = SanitizeValues(sourceItem, Value);
                    }
                    hasValidSource = true;
                    SetModified();
                }
            }
            if (Sitecore.Context.ClientPage.IsEvent)
            {
                string str = Sitecore.Context.ClientPage.ClientRequest.Form[this.ID + "_value"];
                if (str != null)
                {
                    if (base.GetViewStateString("Value", string.Empty) != str)
                    {
                        TreeList.SetModified();
                    }
                    base.SetViewStateString("Value", str);
                }
            }
            base.OnLoad(e);
        }
        private string SanitizeValues(Item sourceItem, string value)
        {
            var db = GetDatabase();
            if (value == null || String.IsNullOrEmpty(value.Trim())) return String.Empty;
            var ids = value.Split('|');
            var validItems = new List();
            for (int i = 0; i < ids.Length; i++)
            {
                var item = db.GetItem(new ID(ids[i]));
                if (item.Axes.IsDescendantOf(sourceItem))
                    validItems.Add(item);
            }
            return String.Join("|", validItems.ConvertAll((x) => x.ID.ToString()));
        }
        private bool SourceContainsDataSource()
        {
            return this.Source.ToLower().Trim().StartsWith("datasource=") || this.Source.ToLower().Contains("&datasource=");
        }
        private string GetDataSourceField()
        {
            return StringUtil.ExtractParameter("DataSourceField", Source).Trim().ToLower();
        }
        public new string DataSource { get { return StringUtil.ExtractParameter("DataSource", Source).Trim().ToLower(); } }
		
        private string GetSourceFromField(string fieldName)
        {
            if (String.IsNullOrEmpty(fieldName)) return String.Empty;
            Item item = CurrentItem();
            if (item == null) return String.Empty;
            Field field = item.Fields[fieldName];
            if (field == null) return String.Empty;
            string fieldValue = field.GetValue(true);
            if (fieldValue == null) return String.Empty;
            return fieldValue;
        }

        private Item CurrentItem()
        {
            return Sitecore.Context.ContentDatabase.GetItem(new ID(base.ItemID));
        }

        private bool IsPathOrGuid(string fieldValue)
        {
            return Sitecore.Data.ID.IsID(fieldValue) || fieldValue.StartsWith("/", StringComparison.OrdinalIgnoreCase);
        }
        private Item ResolveItem(string fieldSource)
        {
            var db = GetDatabase();
            Assert.ArgumentNotNull(db, "Database");
            if (db == null) return null;
            if (Sitecore.Data.ID.IsID(fieldSource))
                return db.GetItem(new ID(fieldSource));
            if (fieldSource.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                return db.GetItem(fieldSource);
            return null;
        }
        private new Database GetDatabase()
        {
            return Sitecore.Context.ContentDatabase;
        }
        private string GetTypeIncludeTemplates()
        {
            Item item = CurrentItem().Parent;
            if (item != null)
            {
                string customControlParentFieldName = ConfigurationManager.AppSettings["CustomControlParentFieldName"];
                if (item.Fields[customControlParentFieldName] != null && !string.IsNullOrWhiteSpace(item.Fields[customControlParentFieldName].Value))
                {
                    string type = item.Fields[customControlParentFieldName].Value;
                    Item typeItem = ResolveItem(type);
                    if (typeItem != null)
                    {
                        string typeName = typeItem.Name;
                        string dataSource = StringUtil.ExtractParameter(CMSConstants.CustomDataSource, Source).Trim();
                        if (!string.IsNullOrWhiteSpace(dataSource))
                        {
                            List typeDataSources = new List();
                            typeDataSources = dataSource.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            if (typeDataSources != null && typeDataSources.Count() > 0)
                            {
                                foreach (string typeSource in typeDataSources)
                                {
                                    if (typeSource.ToLower().Contains(typeName.ToLower()))
                                    {
                                        string appSettingKey = typeSource.ToLower().Replace(typeName.ToLower() + ":", string.Empty);
                                        if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings[appSettingKey]))
                                            return ConfigurationManager.AppSettings[appSettingKey];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return string.Empty;
        }
    }
}

5. Custom Required Field Validator
  
using Sitecore.Data.Validators;
using System;
using System.Runtime.Serialization;

namespace SitecoreCustom.Web.Extensions.CustomFields
{
    [Serializable]
    public class CustomRequiredFieldValidator : StandardValidator
    {
        public override string Name
        {
            get
            {
                return "Required";
            }
        }
        public CustomRequiredFieldValidator():base()
        {
        }
        public CustomRequiredFieldValidator(SerializationInfo info, StreamingContext context):base(info, context)
        {
        }
        protected override ValidatorResult Evaluate()
        {
            if (!string.IsNullOrEmpty(this.ControlValidationValue))
                return ValidatorResult.Valid;
            this.Text = this.GetText("Field \"{0}\" must contain a value.", this.GetFieldDisplayName());
            return this.GetFailedResult(ValidatorResult.FatalError);
        }
        protected override ValidatorResult GetMaxValidatorResult()
        {
            return this.GetFailedResult(ValidatorResult.FatalError);
        }
    }
}

These custom code files can also be downloaded from here

Comments

Popular posts from this blog

GraphQL for Sitecore: A beginner walkthrough

If you are a beginner in GraphQL and you are looking step-by-step by process to setup GraphQL API on Sitecore, please proceed further and setup up GraphQL API for Sitecore Before we jump start Sitecore GraphQL API, let us start some basic introduction of GraphQL. What is GraphQL GraphQL is a query language GraphQL provides a complete and understandable description of the data in your API It gives the power to ask exactly what you need and nothing more Designed to support the needs of the front-end Strongly typed, self-documenting Bandwidth efficient Easy real-time data Sitecore GraphQL API The Sitecore GraphQL API is a generic GraphQL service platform on top of Sitecore. It hosts your data and presents it through GraphQL queries. The API supports real-time data using GraphQL subscriptions Get GraphQL by installing the JSS server components package Sitecore GraphQL does not have any GraphQL endpoints defined by default Define at least one endpoint to use the GraphQL...

Sitecore 9.3 Installation | Common Issues and Resolutions

Recently, I have installed and setup Sitecore 9.3 on another machine. I faced similar/same kind of issues which I faced earlier. Thought, it would be helpful to the Sitecore Community if I capture and document them along with resolution steps I which took and be successful in settting up. Here are few of them I could document them. 1. Failed to start service 'Sitecore Marketing Automation Engine - sitecore93xconnect.dev.local-MarketingAutomationService (sitecore93xconnect.dev.local-MarketingAutomationService)'. Solution : This issue occurs because of non-self-signed certificates, hence please follow the below steps to resolve your issue. Execute below PowerShell script to find out if there are any non-self-signed certificates: 1. Open the PowerShell Console (Admin mode recommended) 2. Execute below command Get-Childitem cert:\LocalMachine\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} 3. If it shows any results listing any non-self-signed certificates...