Leveling Up A Kentico Kontent Project - Part 2
Make sure you have read part one of Leveling Up a Kentico Project before continuing on. Reminder, in the first part, I reviewed mostly the coding issues of updating my Kentico Cloud ASP.Net MVC site to .Net Core 2.1, the Kentico Cloud Delivery SDK 4.14, and other technical issues with getting the solution running. But all that was really to get me ready to something much more intriguing.
In the second part of this mini blog post series I will focus on how I added support for some new Kentico Cloud features.
Let the Fun Begin, New Kentico Cloud Features
Without further ado, let's check out the new features that I added to my project.
First let's get started or illuminate the situation about Webhooks in Kentico Cloud. As the documentation states:
Webhooks allow you to integrate Kentico Cloud with other software applications and automate your processes. Think of Webhooks as programmatic notifications that let your application know when something changes inside your Kentico Cloud project.
This idea is pretty much becoming an industry standard way on syncing data from one system to another across the web, so I am very pleased to see that Kentico Cloud is offering it. In case you are not familiar with them this article on the difference between Webhooks and APIs does a great job of telling the whole story.
The use case that interested me the most with Kentico Cloud Webhooks is the one about invalidating a cached item in memory once a new content item is published. This is something that, to be honest, I never had quite right in the old version of CaseStream.net. Luckily the new Kentico Cloud Boilerplate has a full example on how to get this working. Again this was one of the main reasons I went through the trouble of upgrading.
To start you can follow the documentation example on how to Create a webhook here. It should get you something like below:
After that the key thing that I learned is to make sure you place the Secret in the correct appsettings.json file. I say correct because I actually was using the Debugging configuration option that didn't match this file (Debug vs. Staging).
Now one thing that Kentico could totally improve on here is that, after I did my very first publish of a content item with a Webhook configured, nothing happened. Not a thing. The page didn't update as I thought it would on my staging build. And in the Kentico Cloud application interface there is no log. Hint for Kentico: providing a log to see the last 10 or so triggered Webhooks would be super nice! To get around not seeing anything I had to actually go the ngrok route and tunnel into my local machine to actually step through the code that handles the Webhook. By the way ngrok rocks if you have not used it before. I would definitely check it out.
Pro Tip: When using ngrok, don't forget to add the -host-header command line switch to add in "localhost:5959" or whatever port your using for local dev, else you will get the dreaded Invalid Host Header error when you first start it.
SInce I could now step through the code of the receiving end of the webhook, I noticed where the real problem was, and why it looked like nothing was happening. The generated signature did not equal the KenticoCloudWebhookSecret based signature. That is why it looked like nothing was happening because it was just returning an Unauthorized result in the response.
Once I got past the setting mismatch, it all just worked. I could edit a content item in Kentico Cloud, click publish, and within about a minute my page on www.Casestream.net updated. Pretty cool! You can use Webhooks to do other things as well, like update a search index in Azure Search, or post to a Slack channel, or update your Zoho CRM system. Again, I think the Kentico Cloud Community team has done a heck of a job making the Delivery API SDK for .Net and the Kentico Cloud Boilerplate. All of this would be daunting to start out with, but you don't have to start from scratch. It's already all there in Github for you.
Image Transformations via the Delivery API
The next feature that I was interested in was the new ability for Kentico Cloud assets to be delivered in a responsive fashion via the Image transformation ability. The Kentico Cloud Delivery API now will generate and transform dynamic images based on URL parameters. There are a few small limitations of course, but overall the feature set is impressive. The very first day I looked at it I was kind of blown away and mentioned it on Twitter.
Getting my hands dirty today with the excellent @kenticocloud Image Transformation functionality of the Delivery API. https://t.co/weARye1jBA . The ability to set a focal point crop is pretty neat. #HeadlessCMS— Brian McKeiver (@mcbeev) July 21, 2018
Now the docs and tutorials show the functionality being used with standard image tags and the srcset attribute of HTML 5.0. This is good for some scenarios but not all. I wanted to test it out on the home page of CaseStream.net. But that main home page image is actually a background image only, not an image tag. This is because we place some call to action text and a call to action button right there on top of the image.
In the previous version of the site, that image was downloading the full 40 kb jpg file no matter who was looking at it. Even if the image only needed to be about 200 px tall on a mobile device (vs a desktop device) it still was 40 kb. Now by simply adding a ?h=200 to the end of the URL for the asset, the size from the Delivery API is being rendered as 14 kb. That's a nice savings and speed optimization for mobile. Who wouldn't want to save 65% on a download to the mobile phone? Can your traditional CMS do that over a global CDN without any custom coding (on the backend)? And that is just one image.
To pull it off I did have to create a custom HTML helper on the front end view. The code is shown below where I created the AssetBackgroundImage method:
The backend C# code for the solution is below. Basically the idea we use to leverage responsive images for background images is to render inline style tags with the correct background-image overrides per breakpoint. Please note: I am not a front end developer, this could be not the prettiest CSS out there. If you have a better way to do this, let me know in the comments.
Full disclosure: I did use the boilerplate's AssetImate HTML Helper for "inspiration" on all of this code.
The proof of the solution is in the view source of the home page on www.CaseStream.net. Click on the image below to see the full Google Chrome inspector where the styles are being used.
Along the way I refactored a small amount of code to clean up the solution a little, and it was time to test out the final result. We host CaseStream.net in Azure because it so crazy nice to manage. So I was able to automatically tie the master branch of the repo to a new Deployment Slot in a matter of minutes. During that process I did notice that the staging Deployment slot to the *.azurewebsites.net URL of the staging site was under SSL. During the process of troubleshooting the Webhooks, I noticed our production site was not yet under SSL. I know shame on me. I decided to fix that too.
To correct my insecureness, I used Let's Encrypt for Azure, which is a free Azure Extension. I heavily recommend Scott Hanselmans blog post on Securing an Azure App Service to accomplish installing Let's Encrypt. This was another 45 mins or so, but well worth it. CaseStream.net is now fully under SSL.
I was able to test everything out earlier today, after all my work, and the updated site is now live.
All of this work took me about 2 full days over the last two weekends. To summarize, here are the release notes of my Leveled Up Kentico Cloud site:
- Updated .Net Core 1.1 -> 2.1
- Updated Kentico cloud-boiler-plate 2.0 -> 2.1.2
- Updated Kentico Cloud SDK version 4.1.0 -> 4.14.0 (with latest commits)
- Added SSL support via Let's Encrpt on Azure
- Added Kentico Cloud Webhook support for cache invalidation when a page gets published
- Added Responsive Image for home page banner image via Kentico Cloud Image transformations in the Delivery API
I guess that means we need to update our case study to say www.CaseStream.net: built in 14 days.
Have you tried Kentico Cloud yet?