In this lesson, you will learn how to design modular Blazor UIs that dynamically adapt their structure and branding based on the current tenant's identity.
In a multi-tenant system, "one size fits all" rarely works. Tenants often require custom branding, specific feature modules, or unique navigation flows. Rather than hardcoding these differences, we leverage the Tenant Context to inject component logic at runtime.
Dynamic Component Selection
The most efficient way to achieve this in Blazor is by using the <DynamicComponent /> tag combined with a custom ITenantService. Instead of embedding static components, you resolve the appropriate component type based on the tenant's configuration.
// In your Razor component
<DynamicComponent Type="@TenantFeatureComponent" Parameters="@parameters" />
@code {
[Inject] private ITenantService TenantService { get; set; }
private Type TenantFeatureComponent =>
TenantService.CurrentTenant.Theme switch {
"Enterprise" => typeof(EnterpriseDashboard),
"Startup" => typeof(StartupDashboard),
_ => typeof(DefaultDashboard)
};
}
Decoupling via Strategy Pattern
To avoid bloating your Razor files with if/else logic, treat your UI modules as a collection of strategies. By registering UI components into your Dependency Injection container based on the tenant's ID, you can use keyed services to inject exactly what the tenant needs.
For instance, if a tenant requires a specific compliance-reporting widget, your DashboardLayout doesn't need to know about that widget's internal implementation. It simply requests an IWidget from the DI container, which the infrastructure resolves based on the tenant’s subscription level or unique identifier.
This modular approach ensures that your codebase remains maintainable as you add more tenants. You aren't modifying the core application logic to accommodate new customers; you are simply registering a new UI "plugin" that the system automatically consumes based on the incoming domain or authentication header.
Key Takeaway: Use the DynamicComponent tag and keyed dependency injection to resolve UI modules at runtime, ensuring your Blazor frontend remains clean, modular, and tenant-agnostic.