Использование ConfigurationDbContext в IndetityServer4 из разных API

После решения моей первоначальной проблемы с добавлением UserManager в API (Создание пользователя с помощью IdentityServer4 из нескольких API), который не инициализирует IdentityServer4 (который, в свою очередь, инициализируется внутри веб-приложения, отвечающего только за регистрацию и вход пользователей в систему), я столкнулся с другой проблемой. Из того же API я хочу также получить клиентов и ресурсы из IConfigurationDbContext IdentityServer4.

Пока я пытаюсь сделать следующее: я добавляю ConfigurationDbContext при запуске API, а затем через ClientsController и ClientsRepository я пытаюсь получить доступ к клиентам, как показано ниже.

Startup.cs

 services.AddDbContext<ApplicationDbContext>(options =>
        options.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXX"))
    );

 services.AddDbContext<ConfigurationDbContext>(options =>
        options.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXXX"))
    );

  services.AddIdentityCore<ApplicationUser>(options => {
        options.Password.RequireNonAlphanumeric = false;
    });
    new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole), services)
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddSignInManager<SignInManager<ApplicationUser>>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

ClientsRepository.cs (в .DataAccess):

private readonly IConfigurationDbContext _context;
public bool AutoSaveChanges { get; set; } = true;

public ClientRepository(IConfigurationDbContext context)
{
    _context = context;
}

public Task<Client> GetClientAsync(int id)
{
    return _context.Clients
        .Include(x => x.AllowedGrantTypes)
        .Include(x => x.RedirectUris)
        .Include(x => x.PostLogoutRedirectUris)
        .Include(x => x.AllowedScopes)
        .Include(x => x.ClientSecrets)
        .Include(x => x.Claims)
        .Include(x => x.IdentityProviderRestrictions)
        .Include(x => x.AllowedCorsOrigins)
        .Include(x => x.Properties)
        .Where(x => x.Id == id)
            .SingleOrDefaultAsync();
 }

Однако я получаю следующую ошибку:

System.InvalidOperationException: Unable to resolve service for type 'IdentityServer4.EntityFramework.Interfaces.IConfigurationDbContext' while attempting to activate 'XXXXXX.Data.Repositories.ClientRepository'. 

Я предполагаю, что он снова должен что-то делать с запуском служб, но я не могу его найти.

Кто-нибудь решал что-то подобное?

Лучший, Мариос.


person mkanakis    schedule 08.02.2019    source источник


Ответы (1)


Просто используйте расширения ServicesCollection, которые уже есть в пакете IDS4.EFCore, если вы хотите использовать их:

        services.AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder => builder.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXXX"));
        });

Это добавит вам IConfigurationDbContext, чтобы впоследствии его можно было использовать в других службах через DI.

Используйте следующие статические методы, если вы хотите добавить его непосредственно в ServicesCollection:

    public static IServiceCollection AddConfigurationStore(this IServiceCollection services,
        Action<ConfigurationStoreOptions> storeOptionsAction = null)
    {
        return services.AddConfigurationStore<ConfigurationDbContext>(storeOptionsAction);
    }

    public static IServiceCollection AddConfigurationStore<TContext>(this IServiceCollection services,
    Action<ConfigurationStoreOptions> storeOptionsAction = null)
    where TContext : DbContext, IConfigurationDbContext
    {
        var options = new ConfigurationStoreOptions();
        services.AddSingleton(options);
        storeOptionsAction?.Invoke(options);

        if (options.ResolveDbContextOptions != null)
        {
            services.AddDbContext<TContext>(options.ResolveDbContextOptions);
        }
        else
        {
            services.AddDbContext<TContext>(dbCtxBuilder =>
            {
                options.ConfigureDbContext?.Invoke(dbCtxBuilder);
            });
        }
        services.AddScoped<IConfigurationDbContext, TContext>();

        return services;
    }
person Vidmantas Blazevicius    schedule 08.02.2019
comment
У меня нет никакого метода AddConfigurationDbContext, вы уверены, что это так? Как вы можете видеть, в моем запуске я использовал AddDbContext с ConfigurationDbContext, но, похоже, это не помогает. - person mkanakis; 08.02.2019
comment
@ Davelis4, где объявлено ConfiguratonDbContext? Какую сборку я имею в виду. Кроме того, я отредактировал ответ, я немного ошибся в имени метода. В конце концов, это AddConfigurationStore. - person Vidmantas Blazevicius; 08.02.2019
comment
ConfigurationDbContext объявлен, как и в моем предыдущем вопросе, в WebApp, а не в API, из которого я пытаюсь получить к нему доступ. Кроме того, AddConfigurationStore выдает следующее: IServiceCollection не содержит определения для ... и лучшая перегрузка метода расширения IdentityServerEntityFrameworkBuilderExtensions.AddConfigurationStore(...) требует приемника типа "IIdentityServerBuilder;" - person mkanakis; 08.02.2019
comment
@ Davelis4 Хорошо, честно, я дал вам больше кода, чтобы это работало напрямую с ServicesCollection. Создайте некоторый класс расширения для хранения этих статических методов. - person Vidmantas Blazevicius; 08.02.2019
comment
Это сработало, большое спасибо. Хотя должен спросить, в чем основное отличие? Потому что в моем запуске я сделал что-то подобное, добавив ConfigureDbContext как AddDbContext, но это не сработало. - person mkanakis; 08.02.2019
comment
Что-то я забыл спросить, работает ли это так же для ресурсов, кроме клиентов? Вы пробовали это раньше? Спасибо еще раз. - person mkanakis; 09.02.2019
comment
@Davelis4 Davelis4, да, это сработает и для запроса ресурсов API через контекст. И чтобы ответить на ваш другой вопрос, ваша версия этого не работала, потому что вы добавляли конкретный тип ConfigurationDbContext, но затем вы пытались использовать версию интерфейса в своем контроллере. - person Vidmantas Blazevicius; 09.02.2019
comment
Я использую многопользовательское приложение, так как настроить хранилище конфигурации на основе учетных данных арендатора? - person vijay; 22.02.2021