Blazor Multitenant Configuration with Azure App Configuration Service

Tom McCartan 5 Reputation points
2024-05-01T17:47:48.67+00:00

I have read the following article, but no where in this document does it talk about how this can be instantiated within your program.cs or startup using builder.Configuration.AddAzureAppConfiguration

https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/service/app-configuration

In a typical Multi-Tenant app, we are using Azure Front Door and injecting a Header specifying the Customer ID. We also have a custom route.

Using this in the program.cs we can get all the Azure App Settings for a section. This is assming the GUID there is the customer ID.

// Retrieve the connection string

//string connectionString = builder.Configuration.GetConnectionString("AppConfiguration");

//// Load configuration from Azure App Configuration

//builder.Configuration.AddAzureAppConfiguration(connectionString);

// Bind configuration "TNof1:0bc2b8a2-2500-44e5-858b-9259fc1a6d50" section to the Settings object

//builder.Services.Configure<AppConfigSettings>(builder.Configuration.GetSection("Nof1:0bc2b8a2-2500-44e5-858b-9259fc1a6d50"));

The issue is that the GUID is in the HTTP Header and that needs to be dynamic to get the Azure App Configurations specific for that customer.

So you can follow the recommendations in the article, use a Single Azure App Config, and then identify your settings using Labels, or this hierarchy. But there is no way to dynamically retrieve it in your host startup?

So can this feature be used for multi-tenant in a Blazor Server Side App, hosted in an Azure App Service, using Azure Front Door and using Azure SignalR?

For now, I have resorted to using the Azure App Service Config API Client and retrieving them in my Master Page where I have a persisted state and the HttpContext, which does not seem like the right way to do this, as it does not allow you to use the services in the startup, to use default dependency injection using the IOptionsSnapshot, etc.

Any thoughts on this? It looks like it may have been asked a few times over the past couple years with no solution to this?

Thanks,

Tom

Azure App Configuration
Azure App Configuration
An Azure service that provides hosted, universal storage for Azure app configurations.
209 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,410 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
6,980 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 57,481 Reputation points
    2024-05-01T21:11:00.2966667+00:00

    to get the tenant id you need access to the HttpContext to get the header value. this means the constructor of the service will need to read the settings, rather than passed.

    I probably create a new configuration service that fetched the tenantid from the context, and exposed setting for that context. trival implementation using:

    public class TenantSettings
    {
        private IHttpContextAccessor httpContextAccessor;
        private IConfiguration config;
        private string tentantHeaderName;
        private string TenantId => httpContextAccessor.HttpContext?.Request.Headers[tenantHeaderName] ?? "";
        public TentantSettings(IHttpContextAccessor httpContextAccessor, IConfiguration config)
        {
            this.httpContextAccessor = httpContextAccessor;
            this.config = config;
            tenantHeaderName = config.GetValue<string>("tenantHeaderName") ?? "defaultname";
        }
        public string GetStringValue(string key)
        {
            return config.GetValue<string>($"{TenantId}:{key}");
        }
        public string GetConnectionValue(string key)
        {
            return config.GetValue<string>($"ConnectionStrings:{TenantId}:{key}");
        }
    }
    

    just inject into services to access the settings. you could use different settings stores, prefix, postfix, whatever you want.