Leightweight.Multitenancy.AspNetCore 0.1.0-preview.4

This is a prerelease version of Leightweight.Multitenancy.AspNetCore.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Leightweight.Multitenancy.AspNetCore --version 0.1.0-preview.4                
NuGet\Install-Package Leightweight.Multitenancy.AspNetCore -Version 0.1.0-preview.4                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Leightweight.Multitenancy.AspNetCore" Version="0.1.0-preview.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Leightweight.Multitenancy.AspNetCore --version 0.1.0-preview.4                
#r "nuget: Leightweight.Multitenancy.AspNetCore, 0.1.0-preview.4"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Leightweight.Multitenancy.AspNetCore as a Cake Addin
#addin nuget:?package=Leightweight.Multitenancy.AspNetCore&version=0.1.0-preview.4&prerelease

// Install Leightweight.Multitenancy.AspNetCore as a Cake Tool
#tool nuget:?package=Leightweight.Multitenancy.AspNetCore&version=0.1.0-preview.4&prerelease                

Leightweight.Multitenancy

CI NuGet

Simple multitenancy for your .NET project.

Overview

In a multitenant application, knowing the tenant for the current scope is extremely important. Each tenant may have its own set of resources, such as database, storage accounts, and cache instances. Tenants may even have different functionality depending on how they're configured, or the permissions they've been granted.

This is where Leightweight.Multitenancy comes in. It provides a simple, extensible way to identify and inject the current tenant without all the boilerplate.

Installation

To install the NuGet package, you can use the following dotnet command:

dotnet add package Leightweight.Multitenancy.AspNetCore

Or, via the NuGet package manager console:

Install-Package Leightweight.Multitenancy.AspNetCore

If you're using this in an app that doesn't use ASP.NET Core, you can install the base Leightweight.Multitenancy package, instead.

Usage

To set up a tenant for dependency injection, you can register it with the .NET dependency injection container using the AddTenant<TTenant>().WithResolver<TResolver>() extension methods. Here's an example of how to do this:

services
    .AddTenant<MyTenant>()
    .WithResolver<MyTenantResolver>();

This will register the MyTenant tenant and its MyTenantResolver resolver with the dependency injection container. The MyTenant class doesn't require anything special, but the MyTenantResolver will need to implement the ITenantResolver<MyTenant> interface.

If you're writing an ASP.NET Core application, there is an included middleware implementation that will resolve the tenant. You can register the middleware like this:

app.UseTenant<MyTenant>();

This will add the middleware to the request pipeline and the tenant will be available via dependency injection in any middleware, controllers, or other services that are injected after that point. For more details, check out the samples/AspNetCoreApp/README.md file.

To use MyTenant in your application, you can inject an ITenant<MyTenant> interface into your classes. The ITenant<T> interface is a generic interface that provides access to the current scope's tenant instance. Here's an example of how to do this:

public class MyService
{
    private readonly ITenant<MyTenant> _tenant;

    public MyService(ITenant<MyTenant> tenant)
    {
        _tenant = tenant;
    }

    public void DoSomething()
    {
        if (_tenant.Tenant is null)
        {
            // handle the case where the tenant could not be resolved
        }
        else
        {
            await using var connection = new SqlConnection(_tenant.Tenant.SqlConnectionString);
            // use the connection to execute queries or perform other operations
        }
    }
}

In this example, the MyService class has a dependency on the ITenant<MyTenant> interface. When the service is constructed by the dependency injection container, the current scope's instance of ITenant<MyTenant> is injected into the service.

The DoSomething method uses the Tenant property of the ITenant<MyTenant> to retrieve the current tenant. If the tenant could not be resolved, the Tenant property will be null.

Implementing a Tenant Resolver

To implement a custom tenant resolver, you'll need to create a class that implements the ITenantResolver<TTenant> interface. This interface is generic, so you'll need to specify the type of tenant that your resolver will be able to resolve.

Here's an example implementation of the ITenantResolver<TTenant> interface:

public class MyTenantResolver : ITenantResolver<MyTenant>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyTenantResolver(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public async ValueTask<MyTenant?> Resolve()
    {
        var httpContext = _httpContextAccessor.HttpContext;

        if (httpContext is null)
        {
            // handle the case where the HTTP context is not available
        }

        // TODO: resolve the tenant from the HTTP context

        return new MyTenant();
    }
}

In this example, the MyTenantResolver class implements the ITenantResolver<MyTenant> interface. It has a dependency on an IHttpContextAccessor instance, which is used to retrieve the current HttpContext.

The Resolve method is responsible for resolving the tenant. In this example, it simply returns a new instance of the MyTenant class, but in a real implementation, you would need to use the HttpContext or some other source to identify and resolve the current tenant.

If you need to resolve the tenant from the current request's HttpContext, you can inject an IHttpContextAccessor. You'll need to remember to add the IHttpContextAccessor to your service collection setup. Here's an example of how to do this:

services.AddHttpContextAccessor();

This will register the IHttpContextAccessor with the dependency injection container, and you'll be able to use it to resolve the current HttpContext in your tenant resolver.

Samples

The samples directory contains two example applications that serve as a good starting point for learning how to use this library. One is a console application that resolves two different tenants at the beginning of each application loop and uses the MultitenancyUtilities.PopulateTenant method to manually populate the tenant with the tenant resolver. The other is an ASP.NET core application that resolves the current tenant based on the request's hostname.

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.1 1,499 8/1/2023
0.1.1-alpha.0.1 2,526 8/1/2023
0.1.0 164 5/7/2023
0.1.0-preview.4 103 2/19/2023
0.1.0-preview.3 102 2/16/2023
0.1.0-preview.2 105 2/16/2023