Site Variables in Umbraco 9
Lately I've been experimenting with a concept of Site Variables in Umbraco 9 which I thought I would share with you today.
What's a Site Variable?
Basically a Site Variable is a dynamically added settings object created in the backoffice of Umbraco that you can instantly access in your backend code or even in your views without having to involve config files or custom database tables.
Always with a fallback
Every time you request a Site Variable you are required to provide a default / fallback value in case this variable does not exist in your environment yet or you've misspelled the alias. This way your code will never break if you remove a variable. (More on this later.)
Example: Feature toggle
A good example of a use-case for a Site Variable would be feature toggles. In this example we have a Site Variable used for turning e-commerce features such as a buy button on and off on our website.
Requesting a variable in a view:
(in this example with a hardcoded string alias)
Requesting a variable from the backend:
(in this example with a alias defined in a constant class)
Why not just use a property on a Settings node?
These variables are not supposed to completely replace your Settings node, there are still cases where this is the best place to store your settings. However there are a few cases where I dont think a settings node is the right way to go:
Sharing and deploying variable individually
Some settings makes sense to share, some dont. But if you push your settings node to another environments (using Umbraco Cloud / uSync), let's say from your Stage environment to Production, it's all or nothing! Your can't deploy a subset of properties in your deploy. And chances are your don't want to have exactly the same settings in all of your environments. (For example in your development environments you might have a sandbox API-url in your Settings instead of the production version.) What I like about this Variable approach is that each settings object are individual nodes that can be deployed separately between environments.
Since these variables are just plain built-in nodes, we may also use a lot of the great built-in functionality of Umbraco such as: Scheduling a settings variable to a certain day / time. Let's assume that you had this setting as a property on your settings node, and the client wants to schedule enable commerce until a week from now. Sure you can change that property and schedule the entire settings node for a week from now, but now you have locked the entire settings node. What if you need to update another unrelated setting and this needs to be published before a week from now? You probably get my point here. Since these variables are individual nodes, not only can they be published/unpublished individually, but they may also be schedules individually.
Individual access rights
Again, since these are plain Umbraco nodes, you can also set up individual access rights to each specific variable. Some variables might be "Developer only", some might require Administrator access and some might be totally fine for an everyday editor to update themselves. This would not be possible with a settings node, unless you would set up several settings nodes for each role (DeveloperSettings, AdministratorSettings, EditorSettings etc.) and that seems a little messy.
Before Umbraco 9 we had the <appSettings> section in our web.config that we could use for these kind of settings that we needed to vary between environments (using transform files). These appSettings could also be updated from our code (with the unpleasant site restart) although this was not recommended if you use Source Control. In Umbraco 9 the app settings section in the web.config is now a thing of the past and since this is .NET 5, we need to use the appsettings.json file. The difference here (besides that it's now JSON) is that this file shouldn't be updated at runtime and I heard that some Umbracians are missing the old <appSettings> section for these kind of settings that you don't necessary want to add to a settings node but still need to be able to change after the site started. Maybe these Site Variables could be a good replacement? I'm just thinking out loud here. 😉
Besides the convenience of all the things I've mentioned so far, one of the things I like the most with this concept is the the temporary nature of these settings variables. You may need to quickly add a variable that you only need for a short period of time and while true that you could just add that as a property on your settings node, my experience is that these "temporary" settings never gets removed once they are not needed anymore.
Code changes. ALL THE TIME!
A quick scan through our biggest projects shows that around 10-20% of the settings properties on the settings node are no longer in use. They were probably useful back i the days, but somewhere along the way they've been replaced and now they are just hanging around and confusing the client but no one dares to remove them. Sure this could also happen with Site Variables, but at least your site cant break from removing a Site Variable (read fallback section in the beginning of this post) so the worst thing that can happen is you realise you removed a setting that was in use, so you just add it again in the backoffice. (Or if you are unsure, start by unpublish the variable for a day or two and make sure nothing was impacted, and then remove it.)
Proof of concept
This is still very much in a proof of concept. The code is not magical in any way and has not been made in to a package and probably never will be. But I’ve included it to the UmbracoNineDemo site so if you are interested to use some of the code or concept head over to the GitHub repo and take whatever you like and skip the things you don’t. 😉
Cheers friends! ❤️
ps. Friday blogpost, let's find out if
#umbraCoffee is prerecorded this week! 😉