C
C#5mo ago
Alex

✅ How to get Options from DI

I configured options for google authentication CliendId and ClientSecret.
builder.Services.ConfigureOptions<GoogleOptions>();
builder.Services.ConfigureOptions<GoogleOptions>();
Here I want to get them from ServiceProvider but I don't know how. Should I create ServiceProvider var provider = builder.Services.BuildServiceProvider();?
builder.Services.AddAuthentication()
.AddGoogle((options) =>
{
options.ClientId = "";
options.ClientSecret = "";
});
builder.Services.AddAuthentication()
.AddGoogle((options) =>
{
options.ClientId = "";
options.ClientSecret = "";
});
8 Replies
Omnissiah
Omnissiah5mo ago
using google credentials is a little more involved than that, because depending on the flow you are using you could be reading credentials from environment, from a json file, or even somewhere else you should really follow a tutorial for this, imho
Esa
Esa5mo ago
The MSFT docs for the IOptions<T> pattern are really good, and will answer the general question "How do I use/obtain IOptions<T> from DI?" sufficiently. If your question is more about the google credentials specifically, that's an appropriate question for a thread like this imo.
Alex
AlexOP5mo ago
My question is how can I get options that I configured above exactly in .AddGoogle()?
Esa
Esa5mo ago
I don't know what .AddGoogle() does or where it comes from. But unless it calls .AddOptions<T> and then either
.Configure<IConfiguration>((options, configuration) => /* configure shit */ )
.Configure<IConfiguration>((options, configuration) => /* configure shit */ )
or
.BindConfiguration()
.BindConfiguration()
Then the options haven't been configured. This all assumes you want to bind the options to some values in your configuration. As we mentioned above, this topic does necessitate some understanding so reading the MSFT docs here truly is your best bet.
services.AddOption<SpotifyConfig>()
.BindConfiguration("Spotify")
.Validate(config => !string.IsNullOrWhitespace(config.ApiSecret), "Api secret must be defined!");
services.AddOption<SpotifyConfig>()
.BindConfiguration("Spotify")
.Validate(config => !string.IsNullOrWhitespace(config.ApiSecret), "Api secret must be defined!");
This is an example of how to bind a config class and register it as an Option in your app. When you then create a class and add IOptions<SpotifyConfig> to its parameter list, the DI container will inject that for you. The next immediate question is "but where does it get the values from?" to which the answer is go read the MSFT docs, it'll explain it all in detail 🙂
blueberriesiftheywerecats
dont do BuildServiceProvider cuz calling it from application code results in an additional copy of singleton services being created the easiest way is to use builder.Congifuration to get your properties or you can do
var options = builder.Configuration
.GetSection("[*YourJsonSection*]")
.Get<YourOptions>();
var options = builder.Configuration
.GetSection("[*YourJsonSection*]")
.Get<YourOptions>();
mindhardt
mindhardt5mo ago
Btw $options
MODiX
MODiX5mo ago
appsettings.json:
{
"My": {
"Foo": {
"Kix": 5
}
}
}
{
"My": {
"Foo": {
"Kix": 5
}
}
}
src/Foo/FooOptions.cs:
public class FooOptions
{
public const string SectionName = "My:Foo";

public string Bar {get;set;} = "default value for bar";
public int Kix {get;set;} = -1;
public DateTime? Pouet {get;set;} = default;
}
public class FooOptions
{
public const string SectionName = "My:Foo";

public string Bar {get;set;} = "default value for bar";
public int Kix {get;set;} = -1;
public DateTime? Pouet {get;set;} = default;
}
src/Foo/FooServiceCollectionExtensions.cs:
namespace Microsoft.Extensions.DependencyInjection; // <==== recommanded for service.Add so that you don't clutter Startup file

public class FooServiceCollectionExtensions
{
public static IServiceCollection AddFoo(this IServiceCollection services) =>
services
.AddOptions<FooOptions>()
.BindConfiguration(FooOptions.SectionName)
.Validate(options => options.Kix >= 0, $"The configuration key '{FooOptions.SectionName}:{nameof(Kix)}' cannot be negative")
;

public static IServiceCollection AddFoo(this IServiceCollection services, Action<FooOptions> configure) =>
services
.AddFoo()
.Configure(configure);
namespace Microsoft.Extensions.DependencyInjection; // <==== recommanded for service.Add so that you don't clutter Startup file

public class FooServiceCollectionExtensions
{
public static IServiceCollection AddFoo(this IServiceCollection services) =>
services
.AddOptions<FooOptions>()
.BindConfiguration(FooOptions.SectionName)
.Validate(options => options.Kix >= 0, $"The configuration key '{FooOptions.SectionName}:{nameof(Kix)}' cannot be negative")
;

public static IServiceCollection AddFoo(this IServiceCollection services, Action<FooOptions> configure) =>
services
.AddFoo()
.Configure(configure);
Program.cs / Startup.cs:
services.AddFoo();
// or
services.AddFoo(fooOptions => fooOptions.Kix = 12);
services.AddFoo();
// or
services.AddFoo(fooOptions => fooOptions.Kix = 12);
Bar.cs:
public class Bar
{
private readonly FooOptions _fooOptions;

// .Value in ctor is fine only if it's always ever a non-changing value (no reload and/or no scoped resolution)
public Bar(IOptions<FooOptions> fooOptions)
=> _fooOptions = fooOptions.Value;
}
public class Bar
{
private readonly FooOptions _fooOptions;

// .Value in ctor is fine only if it's always ever a non-changing value (no reload and/or no scoped resolution)
public Bar(IOptions<FooOptions> fooOptions)
=> _fooOptions = fooOptions.Value;
}
Alex
AlexOP5mo ago
Thank you for the answers
Want results from more Discord servers?
Add your server