Skip to main content
Version: 2026.04.0

Verified .NET Quickstart

Use this path when you want the shortest supported Multi-Tenancy setup in an ASP.NET Core API before you add EF Core, RBAC, or external identity providers.

What this path proves

  • Tenant context resolves from a configured request source.
  • Authenticated requests without tenant context are blocked with 401 Unauthorized.
  • Tenant-aware middleware order is clear and minimal.
  • The setup matches the behavior covered by the current-run module test suite.

Prerequisites

  • .NET 9.0 SDK
  • An ASP.NET Core app with authentication already configured

If you do not have authentication yet, start with Identity Validator.

Install the minimum packages

dotnet add package PrimusSaaS.MultiTenancy
dotnet add package PrimusSaaS.MultiTenancy.AspNetCore
dotnet add package PrimusSaaS.MultiTenancy.InMemory

Register services

using PrimusSaaS.MultiTenancy.AspNetCore.DependencyInjection;
using PrimusSaaS.MultiTenancy.DependencyInjection;
using PrimusSaaS.MultiTenancy.InMemory.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(/* your scheme */);
builder.Services.AddAuthorization();

builder.Services.AddPrimusMultiTenancy(options =>
{
options.TenantClaimType = "tid";
options.TenantHeaderName = "X-Tenant-Id";
options.RequireTenantOnAuthenticatedRequests = true;
options.EnableTenantRateLimiting = false;
});

builder.Services.AddPrimusMultiTenancyAspNetCore();
builder.Services.AddPrimusMultiTenancyInMemory();

var app = builder.Build();

app.UseAuthentication();
app.UsePrimusTenantResolution();
app.UsePrimusTenantIsolation();
app.UseAuthorization();

app.MapGet("/tenant/current", (PrimusSaaS.MultiTenancy.Abstractions.ITenantContextAccessor accessor) =>
{
var tenant = accessor.Current;
return tenant is null
? Results.NotFound(new { error = "tenant_not_resolved" })
: Results.Ok(new { tenantId = tenant.TenantId, tenant.DisplayName });
}).RequireAuthorization();

app.Run();

Expected behavior

  1. Send an authenticated request without tid claim, tenant route value, or X-Tenant-Id header.
  2. UsePrimusTenantIsolation() returns 401 Unauthorized with tenant_required.
  3. Send the same request with a valid tenant source.
  4. The endpoint returns the resolved tenant payload.

What this quickstart does not cover

  • EF Core write enforcement
  • Membership-validated tenant switching
  • Distributed rate limiting or distributed membership caching
  • Tenant management endpoints
  • Dedicated-database or schema-per-tenant isolation

Use the Integration Guide when you need those pieces.

Current run evidence

  • dotnet test sdk/dotnet/tests/PrimusSaaS.MultiTenancy.Tests/PrimusSaaS.MultiTenancy.Tests.csproj --no-restore --nologo Current run: 399/399 passed across net8.0, net9.0, and net10.0.
  • dotnet test sdk/dotnet/tests/PrimusSaaS.MultiTenancy.Tests/PrimusSaaS.MultiTenancy.Tests.csproj --framework net9.0 --filter FullyQualifiedName~Regression /p:CollectCoverage=false --nologo Current run: 36/36 passed.
  • sdk/dotnet/tests/PrimusSaaS.MultiTenancy.Tests/Integration/TenantIsolationMiddlewareTests.cs AuthenticatedRequestWithoutTenant_Returns401 passed in the current run.
  • sdk/dotnet/tests/PrimusSaaS.MultiTenancy.Tests/Unit/HeaderStrategyTrustBoundaryTests.cs Current implementation includes membership-validated header selection as the safer production path, even though this quickstart keeps the setup minimal.