← Back to knowledge base |
  • Xperience by Kentico

Setting Up a Solution for Integrating Custom Code in Xperience by Kentico on macOS

In this article, I will guide you through setting up a solution for integrating custom code into an Xperience by Kentico project while developing on macOS.

Recently, I bought a Mac as a complementary machine to my Windows PC 👨‍💻. At that time, I was working on a Next.js project, which is not tied to a specific platform, unlike Kentico CMS or Xperience 13. When I started working on an Xperience by Kentico project, I was pleased to discover that it also supports macOS, so I didn't have to switch back to my PC.

A great introduction to running Xperience by Kentico on macOS is an article written by Kentico's Lead Evangelist, Sean Wright. Combined with the installation guide in the documentation, you should be able to get an Xperience by Kentico project running from a template.

This is how I began working on a client's project. I installed the kentico-xperience-mvc project template and was happily developing a website. However, I encountered challenges when I needed to add customizations to the project, such as configuring a custom rich text editor or setting up a custom autoresponder email. Kentico describes the process of adding customizations in their documentation. Unfortunately, the instructions seem applicable only to Visual Studio on Windows. When developing on macOS using Visual Studio Code, there are several extra steps that might not be clear to everyone. At least, I struggled with it 🤔.

This article aims to be a continuation of Sean Wright's article. It focuses on transforming the project structure of the kentico-xperience-mvc template into a more robust setup, allowing you to add customizations on macOS.

🏃 Starting Point

Here are a few notes on the initial setup and tooling:

  • We will be using Visual Studio Code installed on macOS.
  • Ensure you have the C# Dev Kit extension installed in Visual Studio Code, which provides a Solution Explorer similar to Visual Studio.
  • Also, install the PowerShell extension to run commands within Visual Studio Code. In some scenarios, I encountered issues running commands with the default bash.
  • Follow Sean Wright's article and the official documentation to install a new project based on the kentico-xperience-mvc template.
  • Installing a database might be a bit of a challenge on macOS. Xperience by Kentico uses an MS SQL Server database, which cannot be installed directly on a Mac. You also won't be able to run it in a virtualized Windows environment through Parallels, as recent Macs utilize ARM architecture that is not supported by MS SQL Server. Sean recommends installing it through Docker. I chose a different approach—I am renting a Windows VPS with MS SQL Server installed, allowing me to connect to this remote database. In this case, the database installation command would look like:
dotnet kentico-xperience-dbmanager -- -s "<vps ip address>,<port (usually 1433)>" -d "<database name>" -u "<database username>" -p "<database password>" -a "<password for XbyK Admin>" --license-file "<path to license file>"

Let's begin. You should see the following project structure:

Basic project structure installed from a template

👉 The .sln file

As you can see, there is no .sln file, which typically comes with .NET projects created in Visual Studio on Windows. We need to create one to be able to add a new project where the customizations will reside.

Run the following commands in your project directory to create the .sln file:

dotnet new sln -n "<your solution file name>"
dotnet sln "<your solution file name>.sln" add "<your existing csproj file name>.csproj"

The .sln file should now be created.

sln file added

The Solution Explorer should be available at this point. I had to restart Visual Studio Code to see it, so you may need to do the same.

Solution Explorer

🔧 Adding a New Project for Customizations

It is recommended to keep the customization code in a separate project. Let's create one now. Right-click on the Solution in the Solution Explorer and select New Project. Then choose Class Library and give it a name.

Add a new project in a Solution Explorer

A new folder should appear in your project:

New project added in a solution

Now we need to reference the new project in the original main project. Right-click on the main project in the Solution Explorer, select Add Project Reference, and choose the new project.

Adding a new project reference in Solution Explorer

You should see the new project referenced in the original main project.

Customization project as reference in the main project

📦 Adding NuGet Package References to the Customization Project

When implementing a customization that uses, for example, Xperience by Kentico NuGet Packages, you need to add references to them. Unfortunately, Solution Explorer cannot do this. You need to add the references through the command line:

cd "<your customization project folder>"
dotnet add package "Kentico.Xperience.<required package name>" --version "<version>"

Make sure the package version is the same as the package versions in the original main project. You should see the package referenced.

Xperience package as project reference

📁 Project Restructuring

Initially, I thought the project was ready for implementing customizations at this point. How wrong I was 🫣. When I attempted to implement one, I encountered errors that did not indicate any clear source of problems. After some trial and error, I decided to restructure the project in a way similar to Kentico's community portal. The main contributor to the portal is again Sean Wright, who, from what I know, uses a Mac for development as well. Long story short, this approach worked 🎉. As the Community portal is a complex project, I will summarize the steps to restructure your project.

First, separate the projects and their files into standalone folders like so:

Projects in separate folders

Next, update the reference paths to the customization project in the original main project's .csproj and .sln files.

Updated the reference paths

Finally, add two files, Directory.Build.props and Directory.Packages.props, to the original main project and adjust the .csproj file accordingly.

The Directory.Build.props file

This file is used to share common settings across multiple projects in a solution. Here is mine:

<Project>
  <PropertyGroup>
    <VersionPrefix>29.1.4</VersionPrefix>
  </PropertyGroup>
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <WarningsAsErrors>nullable</WarningsAsErrors>
    <NoWarn>$(NoWarn);NU1504;NU1505;NU1701</NoWarn>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
  </PropertyGroup>
</Project>

The Directory.Packages.props file

This file is used to manage NuGet packages versions across multiple projects in a solution. Here is mine:

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
    <CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
    <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
    <DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="kentico.xperience.admin" Version="29.1.4" />
    <PackageVersion Include="kentico.xperience.azurestorage" Version="29.1.4" />
    <PackageVersion Include="kentico.xperience.imageprocessing" Version="29.1.4" />
    <PackageVersion Include="kentico.xperience.webapp" Version="29.1.4" />
  </ItemGroup>
</Project>

The general rule here is that it removes the package version specification from the .csproj file.

The original main project .csproj file

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="kentico.xperience.admin" />
    <PackageReference Include="kentico.xperience.azurestorage" />
    <PackageReference Include="kentico.xperience.imageprocessing"/>
    <PackageReference Include="kentico.xperience.webapp" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\xbykcustomizations\xbykcustomizations.csproj" />
  </ItemGroup>
</Project>

In the end, your project structure should look like this:

Final project structure

At this point, your solution should be ready to handle custom code 🕺. You can continue by creating a new class in the customization project and, for example, implement a custom autoresponder email or any other feature you need.

🏁 Wrap Up

What a ride 🛹! At this stage, you should be able to run the project using the dotnet run command. If you encounter errors, a good first step might be to delete the obj and bin folders from both projects, as we have moved many files around. If that doesn't resolve the issue, be prepared to troubleshoot further as I did to compile this guide 💪.

About the author

Milan Lund is a Freelance Web Developer with Kentico Expertise. He specializes in building and maintaining websites in Xperience by Kentico. Milan writes articles based on his project experiences to assist both his future self and other developers.

Find out more
Milan Lund