question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Blazor and Razor Pages Support

See original GitHub issue

Just 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:

  1. 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:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
unencodecommented, Jan 10, 2020

@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:

protected override void OnInitialized() { … tenantInfo = httpContextAccessor.HttpContext.GetMultiTenantContext().TenantInfo; return true; }

Is that what you mean? I’m not 100% from the question.

1reaction
AndrewTriesToCodecommented, Oct 8, 2019

@unencode Awesome, thanks for your contribution. I have yet to get into Blazor and I am realizing that I need to do so!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Combining Razor and Blazor Pages in a Single ASP.NET ...
First, you have to add Blazor support into your application. This support will allow you to render Blazor components from a Razor page....
Read more >
ASP.NET Core Razor components
Learn how to create and use Razor components in Blazor apps, including guidance on Razor syntax, component naming, namespaces, and component ...
Read more >
ASP.NET Core Blazor
Blazor Server provides support for hosting Razor components on the server in an ASP.NET Core app. UI updates are handled over a SignalR ......
Read more >
Blazor vs Razor - The Difference Solved
The biggest difference between Razor and Blazor is that Razor is a markup language with C#, while Blazor is the framework that lets...
Read more >
Razor vs Blazor: How it Works for Developers (Tutorial)
Razor generates web pages from Razor pages, web page template files written with C# or VB. ... Blazor fully supports the Razor syntax....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found