If you’ve ever worked on a Sitecore XP project, especially using the Helix patterns, you’ve probably experienced assembly version conflicts with your nuget package dependencies. Essentially, a package referenced in nuget is pulls in a dependency that overwrites an assembly that ships with Sitecore with a newer version, leading to an error.
Sometimes you just need to reference an assembly in your code, but not actually deploy it. At first glance there seems to be no way to do this in the nuget package manager. You can, however, do this directly in the .csproj file.
In this example, I needed to reference Microsoft.AspNet.Owin to work on a feature using federated authentication. When I published my project, it pulled in a bunch of other DLLs, the package’s transitive dependencies, that overwrote the ones Sitecore shipped with. In this example, the easiest solution is to tell MSBuild to not publish this package, since it’s already in the /bin folder. But, we still need to include this package for compilation.
The solution is to add <IncludeAssets>compile</IncludeAssets> to the .csproj in the package declaration. For example, with my Microsoft.AspNet.Owin package, the package declaration would look like this:
In a recent Sitecore XP project, we built a controller route that generates PDFs of the pages on demand. While this worked well functionally, we realized that without any rate limiting, users (or bots) could easily overload the server by repeatedly hitting the endpoint. To prevent performance issues by overloading the server, we needed a simple way to throttle requests to this route.
The MvcThrottle Module
After exploring a few options, we landed on the MvcThrottle module that allows you to limit the number of HTTP requests a client can make to your Web API or MVC endpoints over a specified time window.
MvcThrottle tracks incoming requests based on client IP, endpoint, or custom keys, and enforces rate limits using in-memory or distributed stores. You can configure limits per second, minute, hour, or day, and when a limit is exceeded return a 429 Too Many Requests response.
Implementation in Sitecore XP
Here’s how we integrated MvcThrottle into my Sitecore XP solution:
Add the NuGet Package I added the MvcThrottle package to the Foundation layer of my solution, in this case the Foundation module handling Mvc customizations, using NuGet:
Install-Package MvcThrottle
Register the MvcThrottle Module MvcThrottle is typically registered in Global.asax, but since this is a Sitecore solution, I registered it via the Sitecore initialize pipeline for modularity and to avoid global configurations
using System.Web.Mvc;
using Sitecore.Pipelines;
using MvcThrottle;
namespace MyProject.Foundation.Mvc.Pipelines.Initialize
{
public class RegisterMvcThrottle
{
public void Process(PipelineArgs args)
{
var throttleFilter = new ThrottlingFilter
{
Policy = new ThrottlePolicy(
// Required parameter, set to null if not needed
perSecond: null,
perMinute: 5,
perHour: 100)
{
IpThrottling = true
},
Repository = new CacheRepository()
};
GlobalFilters.Filters.Add(throttleFilter);
}
}
}
Apply the MvcThrottle Attribute Next, I decorated the PDF generation controller action with the [EnableThrottling] attribute to enforce rate limits:
[HttpGet]
[EnableThrottling]
public ActionResult Pdf(string id)
{
// Pdf generation logic...
}
In this case we’re using the defaults configured in the module registration. If desired, you can set custom throttling parameters on each action by passing parameters with the EnableThrottling attribute.
Handle 429 Errors Finally, we need to handle the error thrown when a throttling limit is reached. This should map to a page in your site, like the 404 page, with a useful error. If you have a Foundation error handling module, you can handle it there. The simplest approach is to configure a custom error page for HTTP 429 responses in web.config:
MvcThrottle provided a quick and effective way to protect my PDF generation route from abuse. It’s easy to integrate, works well with Sitecore, and offers enough flexibility for most throttling scenarios. In this example we’re throttling by IP. It’s possible to configure this differently by changing the caching strategy. For example, if your site requires authentication, you could throttle by user id instead.
In the previous post I talked about how to wire up Sitecore Pages to use your local Content SDK editing host. This post will describe how to switch it in your deployed XM Cloud environment.
If you created your XM Cloud project using the auto-generated repository, you got a clone of the XM Cloud starter kit. That project, currently, includes 2 head apps: Next.js and Angular. By default, when you deploy your project, the Next.js app is set up as the editing host. You’ve now brought in a Content SDK app and want to switch the editing host to that one. So, how do you do it?
Turns out, it’s actually pretty simple. In your project root, look for xmcloud.build.json. Open that file, and add this to the renderingHosts section:
The path should be the path to the folder containing the Content SDK app. You’ll also want to set enabled to true, and set it to false for the other rendering hosts (or just remove those other hosts from this file altogether).
Shout out to Dan Solovay for the assist on this one!
The Sitecore XM Cloud Content SDK was recently released, and it offers a trimmed down, focused kit to build websites with XM Cloud. However, this new SDK hasn’t been put into the default starter kit codebase that gets created when you start a new project. This post will show you how to get your local development environment up and running with the Content SDK, and how to connect it to the Pages editor.
Create your project in XM Cloud Deploy
This step is straightforward. Use XM Cloud deploy to create your project, environment, and codebase. This will create you a repository from the xmcloud-foundation-head repository that Sitecore provides. You can also use the code-first approach if you so choose, but for the sake of simplicity this post assumes you let Sitecore create your project.
When the initial deployment is created, go ahead and create your site in the Sitecore Cloud portal. Choose the blank site starter template.
Once that process completes, go to the Desktop (you can find the Desktop from the Settings screen in the portal) and package up your site. You’ll want this to install to your local environments soon. You should also consider adding a Page Content component to the page to see something other than a blank screen when you load the site.
These are the paths you’ll need to package:
/sitecore/templates/Project/<Your Site Collection>
/sitecore/templates/Branches/Project/<Your Site Collection>
/sitecore/system/Settings/Project/<Your Site Collection>
/sitecore/media library/Project/<Your Site Collection>
/sitecore/layout/Placeholder Settings/Project/<Your Site Collection>
/sitecore/layout/Renderings/Project/<Your Site Collection>
/sitecore/layout/Placeholder Settings/Project/<Your Site Collection>
Once your environment is up and running, install the package you just created to your local CM, located at: https://xmcloudcm.localhost/sitecore/
You’ll need to get some environment variables from your local rendering host. Some of these are created when you run init.ps1 to scaffold your containers environment. You can get these from the Docker container, or from the .env file in the /local-containers folder in your project root.
Copy the JSS_EDITING_SECRET and SITECORE_API_KEY values.
To connect to a local CM running in Docker, the steps are similar. Create a .env.local file in the root of your Content SDK project. Add the follwing environment variables:
NEXT_PUBLIC_SITECORE_SITE_NAME=<your Site name from the package> NEXT_PUBLIC_SITECORE_API_HOST=https://xmcloudcm.localhost NEXT_PUBLIC_SITECORE_API_KEY=<your API key copied from the Docker container> JSS_EDITING_SECRET=<your JSS Editing Secret copied from the Docker container> DISABLE_SSG_FETCH=true
Then, in the terminal, run: npm install npm run start:connected
Test your app in your browser at http://localhost:3000. If you did it correctly you should see a white page with the Page Content component you created and packaged previously.
Connect the Pages Editor to your local environment
Finally, we want to be able to edit our content and test our components in our local environment before we push and deploy anything. To do that, we need to set up Pages to use our local editing host.
Go to https://pages.sitecorecloud.io/ and log in, then select your site. By default, you’re editing in your XM Cloud environment. Click the Default Editing Host dropdown and change it to localhost:
Afterward, you will see an error like this:
There’s one more step. We need to tell Pages to use our local CM as well. Open your browser tools (F12) and in the Application tab, add this key to local storage: Sitecore.Pages.LocalXmCloudUrl : https://xmcloudcm.localhost
After you do this, you should see your content rendering with the Content SDK and be able to edit the page.
Content SDK in Docker
This post does not cover is getting the Content SDK host running in a docker container. That isn’t strictly necessary to work locally with the Content SDK. However, if you’d prefer to replace the JSS rendering host with the Content SDK one, that will be covered in a later post.
TLDR: Delete any items without templates from your site’s content tree.
Recently when working with Sitecore Pages and my local docker-ized XM Cloud development environment, I ran into an error using the Pages editor. It had been working the previous week so I was stumped. My only clue was this error in the console: ApolloError: Object or reference not sent to instance of an object.
After scouring the documentation and re-doing my local setup, I was at a loss. Turns out, the solution was simple but (as of yet) undocumented, and probably the result of a recent update to Pages. Scouring the CM logs led me to the issue: items with no template.
Before signing off for the weekend, I had built a new component for this project. I pushed in all the code and serialization changes to my branch and opened a pull request for the team to review. When I came back to work on Monday, I swapped back to the development branch before spinning up my containers again.
Swapping branches and re-running serialization removed all the templates and renderings for my new component. However, it did not remove the test items I had created when developing the component, specifically the datasource items in the content tree. These items now had no template. Clicking them in content editor caused an error. And, it turns out, it was also causing the ApolloError in Pages.
To remove them, I had to use the Sitecore dbbrowser tool, at /sitecore/admin/dbbrowser.aspx. Once I did this, Pages was able to connect to my local environment again without issue.
Things move fast in the world of SaaS products like XM Cloud and Pages. This issue may be fixed next week, or it may hang around for a while. Regardless, it’s best to clean up any content items without a template in your local environments if you swap branches as you work on your project.