That is not a secret – Sitecore always used to prioritize Next.Js framework as the first-class citizen for XM Cloud. All the best and finest features tend to find their way to a given framework in the first place. However, recently, there has been much activity around the .NET Core Rendering Framework which makes a lot of sense given most of us, Sitecore tech professionals, originate from the Microsoft and .NET background. More excitement – that is done on .NET 8, which is the latest LST runtime!
Starter Kit
ASP.NET Core framework was with us for a while, periodically receiving some minor updates and fixes. But let’s be honest: having an SDK on its own is one thing, but receiving a decent starter kit on top of that framework is what makes us developers actually create at scale. And that moment has just occurred – without any loud fanfare, XMC ASP.NET Core Starter Kit went public. Despite this being a very early version and having its own temporal shortcomings, I gave it a try and want to share my findings with you.
What are these shortcomings? Just a few:
- FEaaS and BYOC components are not yet supported, therefore you also cannot use Form since it leverages those
System.Text.Json
serializer is more strict than Newtonsoft which was removed in favor of a built-in solution, thus some components may failSITECORE_EDGE_CONTEXT_ID
variable is not supported
Everything else seems to work the same. There are also some expectations of XM Cloud supporting .NET Rendering at a built-in editing host at some time later in the same manner that works today along with JSS applications, but I do not work for Sitecore and can only make assumptions and guesses without any certainty to it.
First Impression
I forked the repo and cloned the forked code into my computer. Let’s take a look at what we have got there.
- the code varies from what we used to see from XM Cloud Foundation Head starter kit, and that’s understood
- at the root folder we still have
xmcloud.build.json
,sitecore.json
and folders –.config
and.sitecore
xmcloud.build.json
is required for cloud deploy, but does not haverenderingHosts
root section required for editing host(s), as I explained above- there is
headapps
folder to keep the solution file along with .NET projects subfolder(s), currently just a single one –aspnet-core-starter
- there is also
local-containers
folder that contains docker-compose files,.env
, docker files, scripts, Traefik, and the rest of the container assets we got used to - another difference –
authoring
folder contains serialization settings and items as well as .NET framework project for CM customizations - however, there are no
init.ps1
andup.ps1
files, but that is easy to create yourself by stealing and modifying those from XM Cloud Foundation Head
With that in mind, we can start investigating. There is a ReadMe document explaining how to deploy this codebase, but before going ahead with it I of course decided to:
Run Local Containers
There are no instructions on container setup, only for cloud deployment, but after spending a few years with Foundation Head, the very first thing that naturally comes into my mind is running this starter kit in local Docker containers. Why not?
There are a couple of things one should do first prior to spinning up containers.
- Modify settings in
.ENV
file – at least these two:
# Enter the value for SQL Server admin password: SQL_SA_PASSWORD=SA_PASSWORD # Provide a folder storing a Sitecore license file: HOST_LICENSE_FOLDER=C:\Projects
- We need to generate Traefik SSL Certificates. To do so let’s create
.\local-containers\init.ps1
script with the below content:
[CmdletBinding(DefaultParameterSetName = "no-arguments")] Param () $ErrorActionPreference = "Stop"; # duplicates in Up.ps1 scrips $envContent = Get-Content .env -Encoding UTF8 $xmCloudHost = $envContent | Where-Object { $_ -imatch "^CM_HOST=.+" } $renderingHost = $envContent | Where-Object { $_ -imatch "^RENDERING_HOST=.+" } $xmCloudHost = $xmCloudHost.Split("=")[1] $renderingHost = $renderingHost.Split("=")[1] Push-Location docker\traefik\certs try { $mkcert = ".\mkcert.exe" if ($null -ne (Get-Command mkcert.exe -ErrorAction SilentlyContinue)) { # mkcert installed in PATH $mkcert = "mkcert" } elseif (-not (Test-Path $mkcert)) { Write-Host "Downloading and installing mkcert certificate tool..." -ForegroundColor Green Invoke-WebRequest " -UseBasicParsing -OutFile mkcert.exe if ((Get-FileHash mkcert.exe).Hash -ne "1BE92F598145F61CA67DD9F5C687DFEC17953548D013715FF54067B34D7C3246") { Remove-Item mkcert.exe -Force throw "Invalid mkcert.exe file" } } Write-Host "Generating Traefik TLS certificate..." -ForegroundColor Green & $mkcert -install & $mkcert "$xmCloudHost" & $mkcert "$renderingHost" } catch { Write-Error "An error occurred while attempting to generate TLS certificate: $_" } finally { Pop-Location } Write-Host "Adding Windows host" Add-HostsEntry "$renderingHost" Add-HostsEntry "$xmCloudHost" Write-Host "Done!" -ForegroundColor Green
And then execute this script:
There is no up.ps1
script, so instead let’s run docker-compose directly: docker compose up -d
You may notice some new images show up, and you also see a new container: aspnet-core-starter
If everything is configured correctly, the script will execute successfully. Run Sitecore from its default hostname, as configured in .env
file:
From there you will see no significant changes. Containers just work well! Sitecore has no content to interact with the head application. I will add the content from the template but let’s make the could deployment first.
Deploy to the Cloud
ReadMe document suggests an inconvenient way of cloud deployment:
1. Create a repository from this template. 2. Log into the Sitecore Deploy Portal. 3. Create a new project using the ‘bring your code’ option, and select the repository you created in step 1.
For the majority of us, who are on the Sitecore Partner side, there are only six environments available grouped into two projects. These allocations are priceless and are carefully shared between all XM Cloud enthusiasts and aspirants who are learning a new platform. We cannot simply “create a new project” because we don’t have that spare project, so in order to create one we have to delete the existing one. Deleting a project requires deleting all (three) of its environments in the first place, which is half of the sandbox capacity, carrying valuable work in progress for many individuals.
That is why I decided to use CLI instead. Luckily it works exactly the same as it does with Next.Js starter kits, and from .\.config\dotnet-tools.json
you may see that it uses that same version. You deploy the root folder holding xmcloud.build.json
file as a working directory, so there are no changes in execution.
Eventually, once deployed we navigate to XM cloud. I decided to follow the ReadMe and create a Basic site from Skate Park template. Basically, I am following steps 4-18 from the ReadMe file.
As a side exercise, you will need to remove a Navigation component from a Header partial item, located at /sitecore/content/Basic/Basic/Presentation/Partial Designs/Header. Basic site will break in the debugger if you do not delete currently incompatible rendering that has a serialization issue.
Building Dev Tunnel in Visual Studio
Next, let’s open and build the solution in the Visual Studio IDE, which refers to .\headapps\aspnet-core-starter.sln
file. You may see it related to three Sitecore dependencies from Sitecore.AspNetCore.SDK.LayoutService.Client
:
- Transient:
Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces.ISitecoreLayoutClient
- Singleton:
Sitecore.AspNetCore.SDK.LayoutService.Client.Serialization.ISitecoreLayoutSerialize
- Singleton:
Sitecore.AspNetCore.SDK.LayoutService.Client.Serialization.Converter.IFieldParser
Modify .\headapps\aspnet-core-starter\appsettings.json
with the setting values collected from the previous steps. You will end up with something looking as:
Now let’s create a Dev Tunnel in VisualStudio:
There will be at least two security prompts:
If everything goes well, a confirmation message pops up:
Now you will be able to run and debug your code in Visual Studio:
Make a note of the dev tunnel URL, so that we can use it to configure Rendering Host, as described at step 27 of ReadMe. You will end up with something as below:
So far so good. You can now run the website by URL and in Experience Editor. Running in Page will however not work yet due to the below error:
To explain that, Experience Editor runs as a part of CM and pulls content from a GraphQL endpoint on that same CM. Pages instead is a standalone separate application, so it does not have access neither to the endpoint nor to the Rendering Hosts settings item. It only has access to Experience Edge so we must publish first. Make sure you publish the entire Site Collection. Once complete, Page works perfectly well and displays the site:
To explain what happens above: Pages app (which is a SaaS-run editor) pulls Experience Edge for the settings of the rendering editing host (which runs in a debuggable dev tunnel from Visual Studio) and renders HTML right there with the layout data and content pulled from Experience Edge.
Deploy Rendering Host to Cloud
Without much thinking, I decided to deploy the rendering host as Azure Web App, with the assumption that the .NET 8 application would be best supported in its native cloud.
After the Web App is created, add the required environmental variables. The modern and shiny SITECORE_EDGE_CONTEXT_ID
variable is not yet supported with .NET Core SDK, so we should go the older way:
A pleasant bonus of GitHub integration is that Azure creates GitHub Actions workflow with the default functional build and deployment. There is almost nothing to change, I only made a single fix replacing run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/myapp with a hardcoded path since this variable contains space from “Program Files” part and is incorrectly tokenized breaking the build. After this fix, GitHub actions got built the right way and I started receiving green status:
… and the published site shows up from the Azure Web App powered rendering host:
Finally, we can get rid of Dev Tunnel, replacing it with the actual “published site” hostnames:
After republishing the Rendering Host item to Edge, we can stop the debugger and close Visual Studio. Both Experience Editor and Pages app are now working with an editing host served by the Azure Web App.
Verdict
Of course, that would be much anticipated for XM Cloud to have built-in .NET editing host capabilities same way as JSS does. But even without it, I applaud to Sitecore development team for making and keeping working on this starter kit as that is a big milestone for all of us within the .NET Community!
With this kit, we can now start building XM Cloud powered .NET app at a faster pace. I believe all the missing features will find their way to the product, and maybe later there will be some (semi)official SSG support for .NET, something like Statiq. That will allow deployments to a wider set of hosting, such as Azure Static Web Apps, Netlify, and even Vercel which does not support .NET as of today.