Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting IConfiguration in own ServiceCollection

Im making fixture to my tests.

In my FixtureFactory im making my own ServiceCollection:

    private static ServiceCollection CreateServiceCollection()
    {
        var services = new ServiceCollection();

        services.AddScoped<IConfiguration>();
        services.AddScoped<ITokenService, TokenService>();
        services.AddDbContext<TaskManagerDbContext>(o => o.UseInMemoryDatabase(Guid.NewGuid().ToString()));
        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequiredLength = 6;
            options.Password.RequireLowercase = false;
            options.Password.RequireUppercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireDigit = false;
            options.User.RequireUniqueEmail = true;
        }).AddEntityFrameworkStores<TaskManagerDbContext>();

        return services;
    }

Then, im getting this services from scope:

    var services = CreateServiceCollection().BuildServiceProvider().CreateScope();

    var context = services.ServiceProvider.GetRequiredService<TaskManagerDbContext>();
    var userManager = services.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
    var roleManager = services.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
    var signInManager = services.ServiceProvider.GetRequiredService<SignInManager<ApplicationUser>>();
    var tokenService = services.ServiceProvider.GetRequiredService<TokenService>();

The problem starts when i added TokenService to my ServiceCollection.

Constructor, of TokenService looks like this:

    private readonly IConfiguration configuration;

    private readonly UserManager<ApplicationUser> userManager;

    public TokenService(IConfiguration configuration, UserManager<ApplicationUser> userManager)
    {
        this.configuration = configuration;
        this.userManager = userManager;
    }

It works great when i launch my Core app, but wont work from ServiceCollection that i mentioned above.

In Tests, i started to get this error:

Message: System.AggregateException : One or more errors occurred. (Cannot instantiate implementation type 'Microsoft.Extensions.Configuration.IConfiguration' for service type 'Microsoft.Extensions.Configuration.IConfiguration'.) (The following constructor parameters did not have matching fixture data: ServicesFixture fixture) ---- System.ArgumentException : Cannot instantiate implementation type 'Microsoft.Extensions.Configuration.IConfiguration' for service type 'Microsoft.Extensions.Configuration.IConfiguration'. ---- The following constructor parameters did not have matching fixture data: ServicesFixture fixture

This error started to show when i added services.AddScoped<IConfiguration>(); to my ServiceCollection and when i started to get required service TokenService.

My question is, how to register properly Configuration that im using in Service?

Im using Configuration to get items from settings.json.

EDIT:

My fixture and sample test class:

public class ServicesFixture
{
    public TaskManagerDbContext Context { get; private set; }

    public UserManager<ApplicationUser> UserManager { get; private set; }

    public RoleManager<IdentityRole> RoleManager { get; private set; }

    public SignInManager<ApplicationUser> SignInManager { get; private set; }

    public TokenService TokenService { get; private set; }

    public ServicesFixture()
    {
        var servicesModel = ServicesFactory.CreateProperServices();

        this.Context = servicesModel.Context;
        this.UserManager = servicesModel.UserManager;
        this.RoleManager = servicesModel.RoleManager;
        this.SignInManager = servicesModel.SignInManager;
        this.TokenService = servicesModel.TokenService;
    }

    [CollectionDefinition("ServicesTestCollection")]
    public class QueryCollection : ICollectionFixture<ServicesFixture>
    {
    }
}

Tests:

[Collection("ServicesTestCollection")]
public class CreateProjectCommandTests
{
    private readonly TaskManagerDbContext context;

    public CreateProjectCommandTests(ServicesFixture fixture)
    {
        this.context = fixture.Context;
    }
}

EDIT2

When i delete AddScoped<IConfiguration>(); from my collection and run tests, i get this error:

Message: System.AggregateException : One or more errors occurred. (No service for type 'TaskManager.Infrastructure.Implementations.TokenService' has been registered.) (The following constructor parameters did not have matching fixture data: ServicesFixture fixture) ---- System.InvalidOperationException : No service for type 'TaskManager.Infrastructure.Implementations.TokenService' has been registered. ---- The following constructor parameters did not have matching fixture data: ServicesFixture fixture

like image 447
michasaucer Avatar asked Jul 19 '19 15:07

michasaucer


People also ask

What is IConfiguration in .NET core?

The IConfiguration is an interface for . Net Core 2.0. The IConfiguration interface need to be injected as dependency in the Controller and then later used throughout the Controller. The IConfiguration interface is used to read Settings and Connection Strings from AppSettings. json file.

How do I use IOptions in net core 6?

IOptions is singleton and hence can be used to read configuration data within any service lifetime. Being singleton, it cannot read changes to the configuration data after the app has started. Run the app and hit the controller action. You should be able to see the values being fetched from the configuration file.

Is Ioption a singleton?

IOptionsMonitor is a Singleton service that retrieves current option values at any time, which is especially useful in singleton dependencies.

How do I get an instance of the iconfiguration service?

How do we get an instance of the IConfiguration service? Like this: // Add services to the container. In this way, the configuration variable is of type IConfiguration. And so we can get a value from a configuration provider: And that’s it!

How to get iconfiguration from iservicecollection?

Had to call .ImplementationFactory (null). Works but is rather dirty of course. To get IConfiguration from IServiceCollection why not just resolve the dependency?: IConfiguration configuration = services.BuildServiceProvider ().GetService<IConfiguration> ();

How do I set up JSON config providers for servicecollection?

return serviceCollection. BuildServiceProvider (); Add a new file called appsettings.json to test the that json config providers are working fine. In the file add the following: In the Main method we setup everything. Main should look like this: IConfiguration configuration = serviceProvider. GetService < IConfiguration > ();

How to add a service to a configuration file?

To offer using a service in both ways – using the configuration values from configuration files, and passing it directly with the options, you can create both versions of the extension methods AddGreetingService, the one from the previous article and this one. Defining a Configuration File The sample code uses a JSON configuration file.


1 Answers

You added IConfiguration with no implementation.

In startup.cs the framework would have created an implementation behind the scenes and added it. You will have to do the same using ConfigurationBuilder

var builder = new ConfigurationBuilder()
    //.SetBasePath("path here") //<--You would need to set the path
    .AddJsonFile("appsettings.json"); //or what ever file you have the settings

IConfiguration configuration = builder.Build();

services.AddScoped<IConfiguration>(_ => configuration);

//...
like image 150
Nkosi Avatar answered Sep 17 '22 10:09

Nkosi