JonPSmith / AuthPermissions.AspNetCore

This library provides extra authorization and multi-tenant features to an ASP.NET Core application.

Home Page:https://www.thereformedprogrammer.net/finally-a-library-that-improves-role-authorization-in-asp-net-core/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

.net 7 Error Sharding Example

johndcollins opened this issue · comments

Hi Jon, I'm trying to add your Sharding Example to my .net 7 Web App. I'm getting the following error: I can't seem to locate the issue.

System.AggregateException
HResult=0x80131500
Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: AuthPermissions.AdminCode.ITenantChangeService Lifetime: Transient ImplementationType: MyProject.Web.Sharding.ShardingTenantChangeService': Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions1[MyProject.Web.Sharding.ShardingSingleDbContext]' while attempting to activate 'MyProject.Web.Sharding.ShardingTenantChangeService'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Program.

$(String[] args) in C:\MyProject\src\MyProject.Web\Program.cs:line 84

This exception was originally thrown at this call stack:
[External Code]

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: AuthPermissions.AdminCode.ITenantChangeService Lifetime: Transient ImplementationType: MyProject.Web.Sharding.ShardingTenantChangeService': Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[MyProject.Web.Sharding.ShardingSingleDbContext]' while attempting to activate 'MyProject.Web.Sharding.ShardingTenantChangeService'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[MyProject.Web.Sharding.ShardingSingleDbContext]' while attempting to activate 'MyProject.Web.Sharding.ShardingTenantChangeService'.

This is my startup code. It errors on the builder.Build() line

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext(options =>
options.UseSqlServer(connectionString));

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity(options =>
options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores();

builder.Services.AddControllersWithViews()
.AddRazorRuntimeCompilation();

builder.Services.RegisterAuthPermissions(options =>
{
options.TenantType = TenantTypes.SingleLevel | TenantTypes.AddSharding;
options.EncryptionKey = builder.Configuration[nameof(AuthPermissionsOptions.EncryptionKey)];
options.PathToFolderToLock = builder.Environment.WebRootPath;
options.SecondPartOfShardingFile = builder.Environment.EnvironmentName;
options.Configuration = builder.Configuration;
})
//NOTE: This uses the same database as the individual accounts DB
.UsingEfCoreSqlServer(connectionString)
.IndividualAccountsAuthentication()
.RegisterAddClaimToUser()
.RegisterAddClaimToUser()
.RegisterTenantChangeService()
.AddRolesPermissionsIfEmpty(MyProjectAppAuthSetupData.RolesDefinition)
.AddTenantsIfEmpty(MyProjectAppAuthSetupData.TenantDefinition)
.AddAuthUsersIfEmpty(MyProjectAppAuthSetupData.UsersRolesDefinition)
.RegisterFindUserInfoService()
.RegisterAuthenticationProviderReader()
.AddSuperUserToIndividualAccounts()
.SetupAspNetCoreAndDatabase(options =>
{
//Migrate individual account database
options.RegisterServiceToRunInJob<StartupServiceMigrateAnyDbContext>();
//Add demo users to the database (if no individual account exist)
options.RegisterServiceToRunInJob();

    //Migrate the application part of the database
    options.RegisterServiceToRunInJob<StartupServiceMigrateAnyDbContext<ShardingSingleDbContext>>();
    //This seeds the invoice database (if empty)
    options.RegisterServiceToRunInJob<StartupServiceSeedShardingDbContext>();
});

//This is used to set a tenant as "Down",
builder.Services.AddDistributedFileStoreCache(options =>
{
options.WhichVersion = FileStoreCacheVersions.Class;
//I override the the default first part of the FileStore cache file because there are many example apps in this repo
options.FirstPartOfCacheFileName = "MyProjectCacheFileStore";
}, builder.Environment);

//manually add services from the AuthPermissions.SupportCode project
builder.Services.AddSingleton<IGlobalChangeTimeService, GlobalChangeTimeService>(); //used for "update claims on a change" feature
builder.Services.AddSingleton<IDatabaseStateChangeEvent, TenantKeyOrShardChangeService>(); //triggers the "update claims on a change" feature
builder.Services.AddTransient<IAccessDatabaseInformation, AccessDatabaseInformation>();
builder.Services.AddTransient<ISetRemoveStatus, SetRemoveStatus>();

var app = builder.Build();

Looks like I was missing an important step in the RegisterExample6Invoices function. Maybe this should have been named differently :) Really has nothing to do with invoices.

        //Register the retail database to the same database used for individual accounts and AuthP database
        services.AddDbContext<ShardingSingleDbContext>(options =>
            options.UseSqlServer(
                configuration.GetConnectionString("DefaultConnection"), dbOptions =>
            dbOptions.MigrationsHistoryTable(ShardingSingleDbContextHistoryName)));