Pages

07 December, 2021

Sitecore PowerShell - Get All Sitecore Users With Basic Properties

Saving the handy script to get all the Sitecore Users with basic properties like Is Admin, Is locked out, email address etc. 



07 October, 2021

Sitecore 9, 10 - Experience Editor Slow or Hang in general or for non-English languages?

As part of the Sitecore Upgrade to Sitecore 10.0.1, we faced an issue related to experience editor. When we try to edit the page in experience editor for non-english version of the item, the CM website hangs and then it will just block every other requests. Entire CM instance will be unavailable. 

Troubleshooting:

  1. Checked the Vanilla Sitecore 10.0.1 version and experience editor is working as expected. 
  2. Debugged the solution and found out that Dictionary API (Sitecore.Globalization.Translate.Text) is the root cause for the slowness. 
Solution:
Sitecore has reported a similar issue as a known issue for Sitecore 9.3 onwards and the fix was included in Sitecore 10.1.0. Sitecore article has a fix for version 9.3 in their page

Reached out to Sitecore to get the fix for Sitecore 10.0.1 version. For this version, the hotfix has a set of DLLs and a config file. They are not support DLLs. So we should include this as part of the CI/CD pipeline so that it does not get overwritten next time. 

After applying the fix, the experience editor started to respond for all the other languages as well. 

Reach out to Sitecore if your Sitecore version (9.3 to 10.0.1) has a similar issue on experience editor and they will be providing the hotfix for the particular version. 

17 September, 2021

Sitecore PowerShell - Create a report with all referenced items by Lookup Items

In case if you have a list of lookup items and you would like to get a Sitecore PowerShell report of all the referenced items in Sitecore, you can make use of the below script. Also this script demonstrates the usage of PSObject by which you can create custom object and render it in the output window. This approach is using Link database and rebuilding the link database helps you to get the most accurate results. 

With PSObject, you can merge two different object and create a new custom object which can be used for rendering the results. Instead of using multi-dimensional arrays, this can be a better approach. 




02 September, 2021

Sitecore Upgrade - Codebase Upgrade - Migrate from packages.config to PackageReference

We have been always using packages.config file to manage the nuget package references. Instead of config file, PackageReference has been introduced to provide benefits for the developers. 

Benefits:

  1. Instead of showing all the dependencies in the packages.config file, only top level dependencies will be added as part of PackageReference. This gives a clean and simple view on the references. 
  2. Ability to manage all the project level configuration like package references in a single csproj file itself.
  3. Adding and removing packages are faster compared to Packages.config file. 
Migration of Packages.config to PackageReferences
To migration all the existing references, right-click the References node in Solution Explorer, and select the Migrate packages.config to PackageReference command.


Default to PackageReferences:
In order to add packages to PackageReferences by default, open Tools > NuGet Package Manager > Package Manager Settings menu, change the Default package management format to PackageReference.



20 August, 2021

Sitecore Upgrade - Codebase Upgrade - Migrate to SDK Project Format

The older style of csproj has lot of cumbersome tasks like adding files, excluding files, complex in adding references and packages.config file maintenance. 

The new SDK project format was introduced along with Visual Studio 2017. Some of the pros includes:

  • Clean csproj file with the ability to modify the .NET framework or .NET core version
  • Ability to view/edit the csproj file without excluding the project in Visual Studio
  • No need of Packages.json file and include the nuget references as part of csproj file itself
  • No need to include each and every .cs file to the project. 
A typical old csproj format file: You will see so many lines which could have been defaulted somewhere else. 
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
  <Import Project="..\..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{30EB7022-CCB9-48AB-96C1-3556565A51C1}</ProjectGuid>
    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>SitecoreDemo.Feature.Accounts</RootNamespace>
    <AssemblyName>SitecoreDemo.Feature.Accounts</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort />
    <IISExpressAnonymousAuthentication />
    <IISExpressWindowsAuthentication />
    <IISExpressUseClassicPipelineMode />
    <UseGlobalApplicationHostFile />
    <SccProjectName>SAK</SccProjectName>
    <SccLocalPath>SAK</SccLocalPath>
    <SccAuxPath>SAK</SccAuxPath>
    <SccProvider>SAK</SccProvider>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
    <Use64BitIISExpress />
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Microsoft.AI.Agent.Intercept, Version=1.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.1.2.1\lib\net45\Microsoft.AI.Agent.Intercept.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.AI.DependencyCollector, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.1.0\lib\net45\Microsoft.AI.DependencyCollector.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.AI.PerfCounterCollector, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.1.0\lib\net45\Microsoft.AI.PerfCounterCollector.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.AI.ServerTelemetryChannel, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.1.0\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.AI.Web, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.Web.2.1.0\lib\net45\Microsoft.AI.Web.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.AI.WindowsServer, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.WindowsServer.2.1.0\lib\net45\Microsoft.AI.WindowsServer.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.ApplicationInsights, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.ApplicationInsights.2.1.0\lib\net46\Microsoft.ApplicationInsights.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll</HintPath>
    </Reference>
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Web.DynamicData" />
    <Reference Include="System.Web.Entity" />
    <Reference Include="System.Web.ApplicationServices" />
    <Reference Include="System.ComponentModel.DataAnnotations" />
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Web.Extensions" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Web" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Web.Services" />
    <Reference Include="System.EnterpriseServices" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="System.Web.Razor">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Webpages">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Webpages.3.2.3\lib\net45\System.Web.Webpages.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Webpages.Deployment">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Webpages.3.2.3\lib\net45\System.Web.Webpages.Deployment.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Webpages.Razor">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Webpages.3.2.3\lib\net45\System.Web.Webpages.Razor.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Helpers">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Webpages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Web.Infrastructure">
      <HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
    </Reference>
    <Reference Include="System.Web.Mvc">
      <HintPath>..\..\..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="Views\ChangePassword\_ChangePassword.cshtml" />
    <Content Include="Views\ChangePassword\_ChangePasswordEdit.cshtml" />
    <Content Include="Views\Common\_SiteDownAlert.cshtml" />    
    <Content Include="Views\Common\_WelcomeBanner.cshtml" />
    <Content Include="Views\Notification\Preference.cshtml" />
    <Content Include="Views\Notification\UserInfo.cshtml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Attribute\SessionExpireFilterAttribute.cs" />    
    <Compile Include="BusinessLogic\ChangePassword.cs" />
    <Compile Include="Controllers\ChangePasswordController.cs" />
    <Compile Include="Constants.cs" />
    <Compile Include="Controllers\BaseController.cs" />
    <Compile Include="Controllers\NotificationController.cs" />
    <Compile Include="Controllers\ToolsController.cs" />
    <Compile Include="Helper\EnumHelper.cs" />
    <Compile Include="Models\Customer.cs" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Marketing\Marketing.csproj">
      <Project>{1117786e-0ae1-44b0-af00-1ec3adc173ee}</Project>
      <Name>Marketing</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="web.config" />
    <None Include="web.Debug.config">
      <DependentUpon>web.config</DependentUpon>
    </None>
  </ItemGroup>
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DEV|AnyCPU'">
    <OutputPath>bin\</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PROD|AnyCPU'">
    <OutputPath>bin\</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'UAT|AnyCPU'">
    <OutputPath>bin\</OutputPath>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
        <WebProjectProperties>
          <UseIIS>False</UseIIS>
          <AutoAssignPort>True</AutoAssignPort>
          <DevelopmentServerPort>58420</DevelopmentServerPort>
          <DevelopmentServerVPath>/</DevelopmentServerVPath>
          <IISUrl>http://localhost:57567/</IISUrl>
          <NTLMAuthentication>False</NTLMAuthentication>
          <UseCustomServer>False</UseCustomServer>
          <CustomServerUrl>
          </CustomServerUrl>
          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
        </WebProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" />
    <Error Condition="!Exists('..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
  </Target>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

Migrated to SDK format: A simple SDL format csproj file. Readable and easily modifiable. 
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
	<ApplicationIcon />
	<OutputType>Library</OutputType>
	<StartupObject />
	<Authors>Author</Authors>
	<Company>Company Name</Company>
	<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
	<CodeAnalysisRuleSet>$(SolutionDir)\StyleCop.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup> 
  <ItemGroup>
    <Content Include="Views\ChangePassword\_ChangePassword.cshtml" />
    <Content Include="Views\ChangePassword\_ChangePasswordEdit.cshtml" />
    <Content Include="Views\Common\_SiteDownAlert.cshtml" />    
    <Content Include="Views\Common\_WelcomeBanner.cshtml" />
    <Content Include="Views\Notification\Preference.cshtml" />
    <Content Include="Views\Notification\UserInfo.cshtml" />
    <Content Include="Web.config" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Glass.Mapper.Sc.93.Core">
      <Version>5.6.160</Version>
    </PackageReference>
    <PackageReference Include="Sitecore.Mvc" Version="9.3.0" />
    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
    <PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="3.6.0" />
    <PackageReference Include="Sitecore.Kernel" Version="9.3.0" />
    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Models\ExtensionModels\" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\..\Foundation\Extensions\website\SitecoreDemo.Foundation.Extensions.csproj">
      <Project>{a53176ca-ff2g-4b2s-h6j3-1tfs2g94jfb5}</Project>
      <Name>SitecoreDemo.Foundation.Extensions</Name>
    </ProjectReference>
    <ProjectReference Include="..\..\..\Foundation\Marketing\website\SitecoreDemo.Foundation.Marketing.csproj" />
  </ItemGroup>
 </Project>

How to migrate:
There are few options available to migrate to SDK format.

Option 1:
An open source module which does most of the task for us. By simply calling the console app followed by our csproj file will convert most of the project files. We may need to clean up few reference related tasks which will discuss in the next post of the Upgrade series. 


Option 2:
Manually change the csproj file to SDK format. 
  1. Replace entire PropertyGroup with the simple SDK version.
    1. TargetFramework
    2. OutputType
    3. GenerateAssemblyInfo
  2. Remove all compiler related <Import />
  3. Remove all <ItemGroup /> containing .cs files
  4. Remove <ProjectExtensions /> and <Target />
Migrating from packages.json to PackageReferences will be explained in the next blog post.