Skip to content

[EFCore] API throws System.NullReferenceException when using WithClaimStrategy #939

@Alexr03

Description

@Alexr03

Hello,
I seem to be encountering an weird error with using Multi-Tenancy when using WithClaimStrategy.

My project is a Blazor web app, with client-side rendering with rest api backend and am using MultiTenantIdentityDbContext for the identity db context along with my own dbsets.

DbContext:

public class SentryDbContext : MultiTenantIdentityDbContext<SentryUser, SentryRole, string>
{
    public DbSet<SentryScan> Scans { get; set; }
    public DbSet<SentrySteamAccount> SteamAccounts { get; set; }

    public SentryDbContext(IMultiTenantContextAccessor multiTenantContextAccessor, DbContextOptions options) : base(
        multiTenantContextAccessor, options)
    {
        this.TenantMismatchMode = TenantMismatchMode.Overwrite;

    }

    public SentryDbContext(IMultiTenantContextAccessor multiTenantContextAccessor) : base(multiTenantContextAccessor)
    {
        this.TenantMismatchMode = TenantMismatchMode.Overwrite;
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<IdentityUserLogin<string>>().Property("TenantId")
            .HasValueGenerator<TenantDefaultValueGenerator>();
    }
}

SentryUser &, SentryRole both have the the [MultiTenant] attribute.

Multi Tenant:

builder.Services.AddMultiTenant<TenantInfo>()
    .WithClaimStrategy("sentry_tenant")
    .WithStaticStrategy("default")
    .WithInMemoryStore(options =>
    {
        options.IsCaseSensitive = false;
        options.Tenants.Add(new TenantInfo
        {
            Id = "default",
            Identifier = "default",
            Name = "Default"
        });
    });

I have created a user that has the claim sentry_tenant with the value default, and logged in.

When I try to reach an endpoint, I can see in the logs that the tenant is picked up correctly by multi-tenant:

dbug: Finbuckle.MultiTenant.AspNetCore.Strategies.ClaimStrategy[0]
      GetIdentifierAsync: Found identifier: "default"
dbug: Finbuckle.MultiTenant.Stores.InMemoryStore.InMemoryStore[0]
      TryGetByIdentifierAsync: Tenant found with identifier "default"

But once it starts executing the code inside the action, EFCore will throw an error:

      An unhandled exception has occurred while executing the request.
      System.NullReferenceException: Object reference not set to an instance of an object.
         at lambda_method142(Closure, QueryContext)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Collections.Generic.IAsyncEnumerable<TEntity>.GetAsyncEnumerator(CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
         at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
........

However,
If I comment out the WithClaimStrategy or give it a fake authentication scheme as the 2nd parameter (so it falls back onto the static) it will pull the exact same default tenant from the static strategy. and call the same endpoint, it works without errors.

Im confused 😅

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions