Using Umbraco page based configurations in Services

Miklos Kanyo
2 min readNov 30, 2022

Umbraco now supports .NET’s underlying IConfiguration feature i.e. appSettings.json / environment variables / key vaults / etc… which is a great feature. However I found myself in need of a configuration source from a page in Umbraco. In case you store for example settings on your Home page and and you have various services that require the values of these settings you have a number of options to do this including:

  • Reading the configuration values from your Controllers, passing them on to your services methods as parameters
  • Reading the configuration values from the node directly from the service using an injected IUmbracoHelper or IUmbracoContextAccessor

But I found that in my case I did not like either of these options and wanted to have something that’s similar to .NET’s IOptions support. After intensive Googling I still found nothing, so I had to come up with a solution of my own.

I added a custom Configuration type i.e., SearchOptionsand define that as a singleton, only to be created once when first required:

public class SearchOptions
{
public int? MyCustomPageId { get; internal set; }
}
public void ConfigureServices(IServiceCollection services)
{
#pragma warning disable IDE0022 // Use expression body for methods
services.AddUmbraco(_env, _config)
.AddBackOffice()
.AddWebsite()
.AddComposers()
.Build();
#pragma warning restore IDE0022 // Use expression body for methods

services.AddTransient<ISearchService, SearchService>();
services.AddSingleton<SearchOptions>(sp =>
{
var ctx = sp.GetService<IUmbracoContextAccessor>();
var fallback = sp.GetService<IPublishedValueFallback>();

var firstNode = ctx.GetRequiredUmbracoContext().Content.GetAtRoot().FirstOrDefault();

var home = new HomePage(firstNode, fallback);

return new SearchOptions { MyCustomPageId = home.MyCustomPage?.Id };
});
}

With that I could extend my service and have that object injected i.e.

public class SearchService : ISearchService
{
private readonly SearchOptions _options;

public SearchService(
SearchOptions options)
{
_options = options;
}
...
}

Because the SearchOptions is added as a Singleton it means that the logic that reads the homepage is only performed once in the lifetime of the application and you don’t have to worry about performance consequences or having to cache it.

That’s it, I hope this helps someone.

--

--