Reputation: 700
I am having a problem trying to get values from the json file and binding them to the JwtSettings class using the IOptions <> class, but each time the value is null or 0 Startup class:
public class Startup
{
private readonly IOptions<JwtSettings> _settings;
public Startup(IConfiguration configuration, IOptions<JwtSettings> settings)
{
Configuration = configuration;
_settings = settings;
}
public IConfiguration Configuration { get; }
public IContainer ApplicationContainer { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddOptions();
services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));
services.AddJwt(_settings);
var builder = new ContainerBuilder();
//register commandModules
builder.Populate(services);
builder.RegisterModule(new ContainerModules(Configuration));
ApplicationContainer = builder.Build();
return new AutofacServiceProvider(ApplicationContainer);
}
The extensions method when i Use Options:
public static void AddJwt(this IServiceCollection services, IOptions<JwtSettings> setting)
{
IConfiguration configuration;
using (var serviceProvider = services.BuildServiceProvider())
{
configuration = serviceProvider.GetService<IConfiguration>();
}
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.Value.Key)),
ValidIssuer = setting.Value.Issuer,
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
ValidateLifetime = true
};
});
}
On Program class i Add Call ConfigureAppConfiguration when building the Web Host to specify the app's configuration
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);
config.AddCommandLine(args);
})
.UseStartup<Startup>();
The json appsettings looks that:
Upvotes: 1
Views: 7273
Reputation: 463
I kept getting nulls from appsettings.json. In my equivalent to the JwtSettings
class, my property looked like this:
public int QueryLimit { get; }
Didn't think I needed the setter but apparently if you don't include it you get some fun side effects! So it works correctly as follows:
public int QueryLimit { get; set; }
Upvotes: 3
Reputation: 8642
The constructor parameter IOptions<JwtSettings>
is not populated at the time you think it is. When the constructor is called the ConfigureServices
method has not been executed so the framework does not have anything to inject into the constructor except for the default value of JwtSettings
.
Even when you call services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));
this does not populate the IOptions<JwtSettings>
because it has already been injected into the constructor - the framework doesn't update or re-inject the value. This means you have to read the settings yourself within ConfigureServices
(or your extension method) and you can then use the values. e.g.
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));
services.AddJwt(Configuration);
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public static void AddJwt(this IServiceCollection services, IConfiguration configuration)
{
var settings = configuration.GetSection("JwtSettings").Get<JwtSettings>();
....
}
Once the ConfigureServices
method is complete you can inject IOptions<JwtSettings>
into controllers/services and it will be populated.
I know this isn't as clean as using the IOptions<JwtSettings>
parameter but you are trying to use the DI system before it has been initialized so you need to read the settings manually at this point.
Upvotes: 1
Reputation: 4119
I didn't see if you are reading your configurations from your appsettings.json. Where did you specify that? Something like this:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
If you have more than one appsettings. Like(appsettings.Development.json), Prod, etc.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
you need to check the environment variable for your application. Your IConfiguration should take the sections from there
If you have that deployed on your IIS for example, check here:
Upvotes: 0