Saturday, August 27, 2022

Replacement Task Scheduler for Sitecore

In this article we discuss some of the challenges with the out-of-the-box Task Scheduler included with Sitecore and see how you can replace it with Hangfire, a product to perform background processing for .Net applications.


There are ton of articles describing the Task Scheduler and oftentimes cover the same information. Below are few to get you started:

Oddly the only things I can find on the Sitecore docs site is from the old SDN. I'll skip linking that here because it is likely to break.

Some of the issues you'll find with the Task Scheduler is the inability to run at a specific time and if Sitecore shuts down the missed tasks are likely to run immediately following startup. With the use of Hangfire we'll address both issues. The format of the schedule field is also a bit crazy and so we'll add to the complexity by including support for the cron format.

So why not SiteCron? You should use it. If however you can't use it, don't want to use it, or simply can't make up your mind then feel free to give this a try.

Here is a quick breakdown of what we'll build:

  1. Pipeline processor inheriting from Sitecore.Owin.Pipelines.Initialize.InitializeProcessor which should give us access to IAppBuilder. Here we'll register Hangfire and handle scheduling of jobs.
  2. Configuration patch to disable the agent used for scheduled tasks and to register our new processor. There are multiple agents used for scheduled tasks, so at the moment we'll only focus on the one that runs for master in the Standalone and ContentManagement roles.

The important part


Sitecore configuration patch to register the code:

Explanation:
  • Register processor in the own.initialize pipeline. The first option allows you to provide the amount of time to delay running scheduled tasks after Sitecore starts up; this is extremely helpful if you want to disable jobs and need some extra time or the jobs are process-intensive and you want to give Sitecore time to warm up. The second option allows you to adjust the frequency in which schedules configured in Sitecore (from the Content Editor) are updated in Hangfire; this is important for cases where Admins create/update/remove scheduled tasks.
  • Disable the the Master_Database_Agent so the old scheduler doesn't run.
Sitecore processor:

Explanation:
  • You'll need references to Hangfire.AspNetHangfire.Core, and Hangfire.MemoryStorage found on Nuget. I went with in-memory storage because I like things simple and having to setup connections to a database and custom tables sounds like a pain. Also, I feel like looking at the LastRun field was enough to satisfy what I needed.
  • In the Process method we do the basic configuration for Hangfire. I don't care about the dashboard like described here and here. Once again, I like things simple and adding another thing to maintain is just not for me. If you want to then go knock yourself out. We also schedule a fire-and-forget background job to initialize the scheduler which includes registering Scheduled Tasks defined in Sitecore.
  • Once the first background job runs, which may execute tasks that missed their scheduled run time, the recurring jobs are configured. Any scheduled task with an empty/invalid schedule is ignored. The creation of the recurring jobs are chained to the Initialize method so we can ensure that anything missed runs before we schedule others. This may be a problem if you have really long running jobs.
  • The default schedule format {start timestamp}|{end timestamp}|{days to run bit pattern}|{interval} is compatible but converted to a cron schedule format when registered (see GetSchedule method). The interval may be converted to a precise time when using the daily TimeSpan format. For example, the value 1.04:30:00 will run daily at 4:30 AM. The conversion code produces a cron format 30 4 * * * which is what ultimately gets provided to Hangfire. If you want to replace the default schedule format with a cron schedule format go right ahead as both formats are supported. The only problem I saw with this is when using the SPE Task Manager because the tool doesn't know anything about cron.


We've had it running for quite some time now and it has been a game changer for us. Think of all the scheduled tasks that seem to randomly run during deployments or competing with processing power needed by Content Editors.

Give it a try and let me know how it works out for you on your projects. Feedback welcome.

More Hangfire:

Disclaimer: After sharing this post I was reminded of an important distinction one should make with bolting on more features to the Sitecore platform. I found Hangfire helped solve an issue we were having with our scheduled tasks. Every day we run tasks that execute SPE scripts and these can be quite CPU intensive. The data belongs in Sitecore and the tasks need to be run outside of business hours (late night or early morning). As a separate application we built a sync with Quartznet using dotnet 6 (latest LTS version at the time) which dramatically improved the developer experience, performance, and maintainability.

Wednesday, May 4, 2022

Windows Hosts Writer 2.0

 Today I'm pleased to announce the release of Windows Hosts Writer 2.0! In this article we'll learn about what is new and how to get started. Also, a reminder about the pain of managing the hosts file.



There are many steps needed to get a website running locally. For traditional sites hosted with IIS you have to add application pools, websites, perhaps configure services accounts...the list goes on. One of the tasks that feel the most tedious is adding entries to the hosts file. If you are not familiar, this is an extension-less file found at C:\Windows\System32\drivers\etc\hosts and contains IP-to-Hostname mappings. Each row will have an IP address such as 127.0.0.1 followed by the hostname such as scms.dev.local

If you open the hosts file you may already see something like the following:


As you can see from the above image, there is not much going on. This file comes in handy when you want a fancy url to loop back to the local machine. So now you must be wondering how does Windows Hosts Writer (WHW) relate to this? When paired with Docker it can save a tremendous amount of time in managing the everchanging IP addresses.

A while back Rob introduced the Sitecore community to a neat tool distributed through its own Docker container. Check out his series of articles detailing the improvements made over time.

Finally, what is so important about this new 2.0 version of WHW? I'm glad you asked before bailing out on this lame blog post. Below is a breakdown of all the goodies.

  • Support for .net 3.1 ends December 3, 2022 while 6.0 is the latest version released with LTS. We went ahead and upgraded before we forget.
  • Fixed an issue with the TERMINATION_MAP feature. 🥇
  • Aliases that are space-delimited are treated like all the other host entries.
  • Consolidated the Dockerfile which enables contributors to debug locally with Visual Studio, build from docker-compose.yml, and ensure @RAhnemann can still do releases. 👍🏼
  • Encriched the readme with helpful details on getting started. Run docker compose up -d from the root directory to try it out.
  • Updated the referenced Docker.Dotnet assembly to address the dreaded exception Docker.DotNet.DockerApiException: Docker API responded with status code=BadRequest, response=400 Bad Request. This might have been revealed after upgrading Docker to 4.7.1.
If you want to get started, check out the readme on GitHub. The Docker images have been pushed to DockerHub here.

Friday, August 14, 2020

Unicorn Serialization for SXA Projects Part 2

 In a previous article I shared how I configure Sitecore projects with Unicorn when developing sites for SXA. In this article I share some improvements that can be made to simplify the number of configuration files you have to manage.

At this point you may have heard that Sitecore 9+ includes a capability for altering configuration files using custom defined application settings. Kamruz Jaman has written a detailed article covering many aspects of the features.

Let's have a look at what can be added to your configurations to control them per environment.

Begin by starting with a structure similar to this:



The part that is new and most interesting is the namespace added called environment. For this to function we need the "Web.config" to define it.


This is going to tell Sitecore that we have a namespace we intend to use in our configuration patches and for this transformed Web.config the value is "Dev". I like to use "Dev", "Int", "Tst", "Prd" for the environment names.


Let's take a look at a more complete configuration for use with Unicorn.


You'll notice that the include statements have duplicates such as "Forms" and "Content". This is possible because the environment values will limit only one to appear at any given time.


I certainly hope you found this to be helpful. Happy 2020!


Thursday, January 2, 2020

Secure Docker Websites for Sitecore

In this article Michael shares how to configure Sitecore running on Docker locally with HTTPS. A sample repository is provided to help you get started.

If you don't care to read this article and just want the source code then check out this link right here. There you can see how to get thing setup.


The Background


There comes a time when every developer is going to need Sitecore running over HTTPS. If you have been following the progress the Sitecore Demo Team is making with Docker you'll see that getting started is going to be far less complex for everyone. If you have not yet already seen the GitHub repository feel free to do that once you've finished reading this post.

There are a few articles written recent to this post around getting started with Docker running Sitecore. You may find that some eventually are outdated because the Sitecore Demo Team is moving at such a fast pace the instructions in the articles go stale. Nevertheless the articles provide valuable insight into what you need to do for things to run smoothly. I trust that you will take the time to (if not already) to familiarize yourself with Docker. For those that have worked with Sitecore for any amount of time, surely you will appreciate the simplicity Docker brings.

Note: At the time of this article SIF is no longer used for the Sitecore Docker images. I'm very thankful for this because it makes setup much easier to follow on how things work.

Recommended articles:

  • Sitecore Docker for Dummies - This 3-part series is actually the nudge I needed to get started. Mark Cassidy does such a fantastic job covering the basics. No time is wasted on unnecessary tasks, like setting up a Docker Hub account. If you install Docker through Chocolatey no account is needed.
  • Yet Another Sitecore Docker Series - This 9-part series goes into a bit more detail about how the build of images and running containers come together. Rob Ahnemann is very clear about how things work and at times provide a bit of comic relief.
  • Maintain Your Hosts File with a Docker Container - This helps make the management of hosts entries painless. Thanks Rob! Thank you Hosts Writer!
  • Sitecore Docker and HTTPS with Traefik - At the writing of this I've not tested this approach but if Per Manniche Bering says try it then I recommend you do.


For those wondering about Sitecore supporting Docker, there is a question and answer on Sitecore Stack Exchange which provides more detail.

The Setup


The following steps should help you get things rolling and troubleshoot:
  1. Clone the following repository : https://github.com/michaellwest/docker-https.git
  2. Open the file docker-compose.yml to have a look at what is going on. This compose file assumes you have images built and available on your machine for Sitecore 9.3 XM. 
  3. Open the file .env to ensure they match what is used for your built images. You can try to copy the .env file from the Sitecore repository if things don't work right. An example path would be https://github.com/Sitecore/docker-images/blob/master/windows/tests/9.3.x/.env
  4. Open the folder Startup and with an elevated PowerShell console run the createcert.ps1. By default the script creates a Self-Signed Certificate using the DNS "*.dev.local" then installs locally. Files will be generated in the same directory to be used by the running container (pfx and txt files should now exist).
  5. The file startup.ps1 will be used by the running container to install the certificate and configure the HTTPS bindings.
  6. Run docker-compose up.
  7. Navigate to https://docker-https.dev.local/sitecore.
If everything is setup properly you'll end up with a console full of log messages and finally the login screen to Sitecore.

The Magic


I made this video to help walk you through the different parts with a tad bit of colorful commentary.



- I hope you have a wonderful 2020!

Tuesday, December 31, 2019

Thank you Sitecore Community 2019

Amazing how fast 2019 has come and gone. So many hours spent working on and talking about Sitecore. In this post I share my appreciate for those donating through GitHub Sponsors.

GitHub Sponsors


It was a huge surprise to me this year when GitHub accepted my request (due to nominations) for the Beta program of GitHub Sponsors. If you've not heard about it you can read more about it here.


I was so excited the signup started for the beta program. Then much to my surprise the Sitecore community rallied behind me and helped nominate me. I'm confident this increased my chances of getting into the program. Now GitHub Sponsors is out of beta so you too can apply.

Shortly after the sponsors started to sign up one by one. I'm forever grateful for your contributions. In 2019 these beautiful people found me worthy of supporting.


Then I was like


via GIPHY

So you might be asking yourself, "Why support Michael West?". I'm a contributor to the module Sitecore PowerShell Extensions and this requires quite a bit of personal time. I've enjoyed working on it these past several years and your support helps keep me going. If you feel like now is the time you would like to join in then by all means click this link right here!

How have the donations been spent?

  • Purchased beer and root beer at various establishments.
  • Loaded up on 100% Maple Syrup. Don't judge.
  • Renewed SnagIt and Camtasia for the 2019 maintenance year.
  • Covered some expenses for the Sitecore Symposium 2019 trip.
  • Ordered new SPE gifts (stickers, coasters, buttons, etc.). If you are a sponsor and for some reason I haven't given you any of this please let me know. I'll ship it to you right away.
Photo of Michael and Adam
Photo of Michael and Adam at Symposium
Thank you so much to all those who donated through GitHub Sponsors.

Thursday, May 16, 2019

Donut Caching with Custom SXA Components

In this article Michael shares how to make your custom components, built for SXA, support the donut caching feature.

Today we discovered that one of the forms on our site would simply refresh as you hit the submit button. Further investigation revealed that this component was added to the Sitecore cache. Whenever we cleared the cache the component worked as expected, once. Oh no!

The fantastical SXA module supports donut caching which is made visible through a checkbox on the rendering parameters.

Donut caching setting on the Page List component
This setting is added on the rendering parameters template. Not sure which rendering parameter template is used? You can check it out on the component defined under Layouts.



If you navigate to that item you'll see under the template inheritance a base template for caching.


If you wish to add support for this capability just add the template to your custom rendering parameters template.


At the time of this article, the template ID is {6DA8A00F-473E-487D-BEFE-6834350D5B67} and can be easily added in the Raw values mode of the Content Editor.

Note: When cloning components you will probably use the rendering parameters template included with the original component, in which case you don't even have to do anything special.

If you enjoy using SXA and what to share your appreciation to the team or have questions be sure to check out the #sxa channel on Sitecore Chat.

Thursday, December 27, 2018

Sitecore Security for SXA Projects

Every new website requires some level of security configuration before launch. In this article we see one possible solution to applying security to sites built with the Sitecore Experience Accelerator (SXA).

Please note that the following scripts were written before the SXA module included scripts to manage security. I encourage you to evaluate those included out-of-the-box.

Role Configuration

Let's have a look at how the security will be setup for each tenant.


  • Each tenant will be organized by the company name. Companies have their own domain.
  • At least three of the six roles exist for all tenants (Admin, Editor, Developer). Each role inherits from a Base role (Sitecore Client Authoring, Sitecore Client Users) so they can login and manage content.
Tenant roles mapped to Sitecore roles
Running the script will present the user with a dialog like the following:

Dialog before security settings are applied
The dialog lists all of the available SXA tenants as well as any additional domains configured using the switching provider. This can be very helpful when using the Active Directory module because those users are not in the same domain as the tenant.

Show ribbon button using rules

Script Highlights


Let's walkthrough what changes are applied by the script.

Results output after completion
  • Site - Admin role granted access to help cleanup after users.
  • Home - Base role granted access to manage content.
  • Overlay - Admin role allowed to manage overlay content.
  • Data - Base role granted access to manage grandchildren. Prevents users from deleting global folders.
  • Media - Base role granted access to manage available media library folders.
  • Media Library - Base role granted access to manage media for this site.
  • Presentation - Developer role granted access to manage Rendering Variants, Partial Designs, etc.
  • Theme - Developer role granted access to manage media for this theme.
  • Data Templates - Developer role granted access to manage data templates.
  • Publishing Targets - Editor role granted access to publish to any target.
  • Languages - Everyone role granted access to read/write to all languages. This includes the tenant domain and additional domains selected.
  • System Settings - Developer role granted access to manage Modules, Settings, Tasks, and Workflows.
This will of course not cover the granularity that your company requires, but should provide you with a framework for crafting a tool for your own needs.

Hope this inspires you to build something great and share with the community.

The Scripts