Handling missing tenants in ASP.NET Core

My last post about multi-tenants applications with ASP.NET Core Implementing database per tenant strategy on ASP.NET Core I proposed some ideas about tenant providers but I didn’t focused on issues related to missing tenants. This post proposes missing tenant middleware that redirects faulty requests to some public page of company web site.

To get better understanding of my previous work on multi-tenancy in ASP.NET Core and Entity Framework Core 2.0 please go through my following posts as the current one builds on these:

Ideas for handling missing tenants

I expect here that tenants are served by ASP.NET Core web application that works always in context of some tenant. I mean there will be no public content pages with sales or marketing materials and so on. The web application needs some tenant to be available. But what happens when tenant is not found by host header?

One approach is to throw an exception but this is hardly an option with commercial service. Redirect to some public page would be better but making redirects in controllers means duplicated code. It’s possible to build some TenantRequired attribute but I don’t like this idea either.

Building missing tenant middleware

As a working solution I see custom middleware that is added to request processing pipeline. This middleware takes redirect URL as argument and checks if tenant is detected or not. If there’s no tenant available it redirects request to redirect URL.


public class MissingTenantMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _missingTenantUrl;

    public MissingTenantMiddleware(RequestDelegate next, string missingTenantUrl)
    {
        _next = next;
        _missingTenantUrl = missingTenantUrl;
    }

    public async Task Invoke(HttpContext httpContext, ITenantProvider provider)
    {
        if(provider.GetTenant() == null)
        {
            httpContext.Response.Redirect(_missingTenantUrl);
            return;
        }

        await _next.Invoke(httpContext);
    }
}

Notice how redirect URL is given to middleware through constructor injection and tenant provider is argument of Invoke() method call. It was the minimal I was able to achieve without tricking in Startup class of application.

Adding missing tenant middleware to request pipeline

Middleware must be registered during application start-up. Here is the fragment of Configure() method of Startup class.


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // ...

    app.UseMiddleware<MissingTenantMiddleware>(Configuration["MissingTenantUrl"]);

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Although the case of missing tenant is now handled in middleware it doesn’t mean that other classes that expect existence of current tenant should not control if tenant is available or not.

Wrapping up

Without any hacking but leaning to ASP.NET Core features it is possible to handle many unexpected situations in web applications. This blog post focused on multi-tenant applications and a situation where request is made but tenant is not found. Using custom middleware it was possible to build missing tenant middleware that redirects those requests to some public page given in application settings. All the logic is located in missing tenant middleware and no other parts of web application have to take care about redirects in case of missing tenant.



See also

Leave a Reply

Your email address will not be published. Required fields are marked *