Blazor and Razor Pages Support
See original GitHub issueJust wanted to contribute my experience getting Funbuckle.MultiTenant to work with Blazor and Razor Pages on .NET Core 3.0. So far it seems to be working. Perhaps these instructions will help others.
In this example, we’re using EFCore for storing the tenants database and a single shared database for tenants’ data. You can also change the tenant-specific connection string to put one or more tenants into their own databases.
It’s straight forward:
- Create a Blazor server-side app as you normally would. In Startup.ConfigureServices, add services as follows (using your strategy and store options) and make sure to add services.AddHttpContextAccessor().
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
//Tenants Store
services.AddDbContext<TenantDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("TenantDbConnection")));
//Per-Tenant Data Store (Identity is added below)
services.AddDbContext<ApplicationDbContext>();
services.AddIdentity<MultiTenantIdentityUser, MultiTenantIdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMultiTenant()
.WithHostStrategy("__tenant__.*") //https://www.finbuckle.com/MultiTenant/Docs/Strategies#static-strategy
.WithEFCoreStore<TenantDbContext, AppTenantInfo>();
services.AddRazorPages();
services.AddServerSideBlazor();
//Allows accessing HttpContext in Blazor
services.AddHttpContextAccessor();
services.AddSingleton<IEmailSender, EmailSender>();
}
And Startup.Configure:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//2019-10-05 For Finbuckle Multitenant
//Should be at the top of stack as this injects tenant info into httpContext
app.UseMultiTenant();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapControllers();
//2019-10-05 For Finbuckle Multitenant
endpoints.MapControllerRoute("default", "{__tenant__=}/{controller=Home}/{action=Index}");
endpoints.MapFallbackToPage("/_Host");
});
}
ApplicationDbContext:
public class ApplicationDbContext : MultiTenantIdentityDbContext<MultiTenantIdentityUser>
{
public ApplicationDbContext(TenantInfo tenantInfo, DbContextOptions<ApplicationDbContext> options)
: base(tenantInfo, options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionString);
base.OnConfiguring(optionsBuilder);
}
}
}
TenantDbContext:
public class TenantDbContext : EFCoreStoreDbContext<AppTenantInfo>
{
public IConfiguration Configuration { get; }
public TenantDbContext( DbContextOptions<TenantDbContext> options, IConfiguration configuration) : base( options)
{
Configuration = configuration;
}
}
}
Now on any Blazor Page (or Razor component) you can simply inject IHttpContextAccessor to get access to the Finbuckle extension methods. Here’s an example:
@page "/"
@using Microsoft.AspNetCore.Http
@using Finbuckle.MultiTenant
@inject IHttpContextAccessor httpContextAccessor
@{
//Try get TenantInfo from HttpConext.
GetTenantInfo();
@if (tenantInfo != null)
{
<h2>Tenant Info</h2>
<ul>
<li>Identifier: @tenantInfo.Identifier</li>
<li>Id: @tenantInfo.Id</li>
<li>Name: @tenantInfo.Name</li>
</ul>
}
}
@code
{
TenantInfo tenantInfo;
bool GetTenantInfo()
{
if (httpContextAccessor.HttpContext.GetMultiTenantContext().TenantInfo != null)
{
tenantInfo = httpContextAccessor.HttpContext.GetMultiTenantContext().TenantInfo;
return true;
}
else
{
return false;
}
}
}
After this the MutliTenant extensions are available in both Blazor (and Razor Pages).
Hope this helps someone else too. It may not be perfect yet. If you’d like me to help update the docs or do further testing for Blazor (or whatever) I’d be happy to!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:11 (4 by maintainers)
@mynkow if I understand correctly, yes you can override per tenant in a razor component.
It would be a matter of accessing it in OnInitialized for that component or similar:
Is that what you mean? I’m not 100% from the question.
@unencode Awesome, thanks for your contribution. I have yet to get into Blazor and I am realizing that I need to do so!