Reputation: 5162
I have an ApplicationConfigurationSettings class which I am binding the values from the appsettings.json file to. I can get everything bound except the logger LogLevel value, most likely due to the existence of a sub level in the json format of Logging entry.
I bind the class as follows
services.Configure<ApplicationConfigurationSettings>(Configuration.GetSection("ApplicationConfiguration"));
appsettings.json (parts removed for brevity)
{
"ApplicationConfiguration": {
"ConnectionStrings": {
"DevelopmentConnection": "Server=(localdb)\\mssqllocaldb;Database=TestingConfigurationNetCoreTwo_Development;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"ApplicationIconUrls": {
"MaleUserIcon": "https://machineryrestorations.blob.core.windows.net/publicfiles/images/BestMaleUser_32x32.png",
"FemaleUserIcon": "https://machineryrestorations.blob.core.windows.net/publicfiles/images/BestFemaleUser_32x32"
},
"ApplicationInfo": {
"VersionNumber": "1.0.0",
"Author": "Jimbo",
"ApplicationName": "CustomTemplate",
"CreatedOn": "November 20, 2017"
}
}
}
My logger POCO
public class LoggerSettings
{
public bool IncludeScopes { get; set; }
public KeyValuePair<string,string> LogLevel { get; set; }
}
I'm sure it is due to the fact that the binder can't reconcile my LogLevel property with what is in the json file. How can I change my logger POCO to get this to work since I cannot change the Logging format in the json file?
This is how the json provider resolves it when inspecting Configuration from
services.AddSingleton(Configuration);
{[ApplicationConfiguration:Logging:IncludeScopes, False]} {[ApplicationConfiguration:Logging:LogLevel:Default, Warning]}
I just can't seem to set that property up properly in the class so it binds correctly.
Upvotes: 2
Views: 1995
Reputation: 31282
Json object
"LogLevel": {
"Default": "Warning"
}
could not be mapped to public KeyValuePair<string,string> LogLevel { get; set; }
property for a simple reason. What if some time after, the section will be extended with another fields:
"LogLevel": {
"Default": "Warning",
"SomeOtherField": "SomeValue"
}
How should it be mapped to single KeyValuePair<string,string>
? Of course, in your simple case such single key-value object could be potentially mapped, but configuration binder does not go so far in its assumptions, it just does not work in this way.
And I believe it's a good thing because you're trying to shift from strongly-typed POCO to some bag of key-values, it devalues in some degree the whole approach of strongly-typed configuration taken in .net core.
The fix of your problem is quite simple. Just declare LoggingLevel
class with single (for this moment) property Default
of string
type:
public class LoggingLevel
{
public string Default { get; set; }
}
public class LoggerSettings
{
public bool IncludeScopes { get; set; }
public LoggingLevel LogLevel { get; set; }
}
You could go a little further and set the type for Default
property as Microsoft.Extensions.Logging.LogLevel
. Configuration binder will correctly map string value like "Warning"
to enum value LogLevel.Warning
:
public class LoggingLevel
{
public LogLevel Default { get; set; }
}
It could seem an overkill to have such simple POCO, and you will have quite a lot of them for advanced configurations. But that's actually the way to go, strongly-typed, explicit and extensible.
Upvotes: 1