Azure App Service deployment slots and Sitecore.Globals.ServerUrl

I encountered an unusual scenario this week with a 3rd party integration in one of our Sitecore environments running on an Azure App Service.

Essentially, there was some code running within Sitecore that performed a WebRequest back to itself using the Uri snippet:

var requestUri = new UriBuilder(Sitecore.Globals.ServerUrl) {
  Path = "/path/to/controller"

It was returning an unexpected response compared to what I'd see by going directly to the path in the browser.

At first I was convinced it was some unusual caching behaviour on the WebRequest itself - the response wasn't invalid, it was just older than expected and appeared to be stuck at that state, following some investigation and running some test code it because apparent very quickly what was happening!

It's important to know that once this Globals.ServerUrl is populated, and Sitecore ensures it in the httpRequestBegin pipeline, it's stuck with whatever hostname you used in your first requests once Sitecore starts up.

Enter deployment slots: we deploy to an app service deployment slot, warm Sitecore up and run some smoke tests before swapping it into the production slot.

This means while warming Sitecore up in a staging slot, we're making requests to a hostname like - now Sitecore believes that this is its Globals.ServerUrl.

Post swap (there's no recycle happening) our production slot instance of Sitecore has references to a completely different, now unused App Service (slot) and our 3rd party integration code above is inadvertently making requests to the wrong environment.

Ultimately, the solution is to not depend on Globals.ServerUrl if you're using deployment slots - there's no easy solution to refresh that value once it has one and the only other alternative is to force a recycle post swap and lose some of the benefits of deployment slots and the reduced downtime/slow performance.