Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions examples/DotNetCore/MultiTenantApplicationSetup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Multi-tenant application setup

The .NET Azure App Configuration Provider delivers configuration settings to the existing IConfiguration system. Multi-tenant applications using the provider can take advantage of IConfiguration features to retrieve tenant information from requests. The following instructions will demonstrate one way to achieve this application setup.

1. Define the per tenant settings in App Configuration as key-values using key prefixes.

#### Tenant 1

| Key | Value |
|---- |-------|
| Contoso:Name | Contoso Corp. |
| Contoso:Color | Azure |

#### Tenant 2

| Key | Value |
Comment thread
amerjusupovic marked this conversation as resolved.
|---- |-------|
| ExampleTenant:Name | Example Tenant, Inc. |
| ExampleTenant:Color | Green |

2. Setup the options pattern by creating the following classes.

```cs
//
// Tenant info
//
public class TenantSettings
{
public string Name { get; set; }
public string Color { get; set; }
}
```

```cs
//
// Dynamically configure TenantSettings
//
public class ConfigureTenantSettings : IConfigureOptions<TenantSettings>
{
private readonly IConfiguration _configuration;
private readonly IHttpContextAccessor _httpContextAccessor;

public ConfigureTenantSettings(
IConfiguration configuration,
IHttpContextAccessor httpContextAccessor)
{
_configuration = configuration;
_httpContextAccessor = httpContextAccessor;
}

public void Configure(TenantSettings options)
{
//
// Get tenant id from the request
// ex. Read tenant from a request header
if (!_httpContextAccessor.HttpContext.Request.Headers.TryGetValue(
"X-Tenant-Id",
out StringValues tenantId))
{
return;
}

//
// Initialize from config section by TenantId
_configuration.GetSection(tenantId).Bind(options);
}
}
```

3. Register the options as a scoped DI service.

```cs
services.AddScoped<IConfigureOptions<TenantSettings>, ConfigureTenantSettings>();
```

4. Use in a DI Service or Controller via `IOptionsSnapshot`.

```cs
public class MyController : Controller
{
private readonly IOptionsSnapshot<TenantSettings> _tenantSettings;

public MyController(IOptionsSnapshot<TenantSettings> tenantSettings)
Comment thread
jimmyca15 marked this conversation as resolved.
{
_tenantSettings = tenantSettings;
}

[HttpGet]
public IActionResult Get()
{
TenantSettings tenantSettings = _tenantSettings.Value;

// ...
}
}
```
4 changes: 2 additions & 2 deletions examples/DotNetCore/WebDemoNet6/WebDemoNet6/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
// Load all keys that start with `WebDemo:` and have no label
.Select("WebDemo:*")
// Configure to reload configuration if the registered key 'WebDemo:Sentinel' is modified.
// Use the default cache expiration of 30 seconds. It can be overriden via AzureAppConfigurationRefreshOptions.SetCacheExpiration.
// Use the default cache expiration of 30 seconds. It can be overridden via AzureAppConfigurationRefreshOptions.SetCacheExpiration.
Comment thread
amerjusupovic marked this conversation as resolved.
Outdated
.ConfigureRefresh(refreshOptions =>
{
refreshOptions.Register("WebDemo:Sentinel", refreshAll: true);
})
// Load all feature flags with no label. To load specific feature flags and labels, set via FeatureFlagOptions.Select.
// Use the default cache expiration of 30 seconds. It can be overriden via FeatureFlagOptions.CacheExpirationInterval.
// Use the default cache expiration of 30 seconds. It can be overridden via FeatureFlagOptions.CacheExpirationInterval.
.UseFeatureFlags();
});

Expand Down