New configuration system of.NET core is really nice, but it does not works very well with arrays, I have a configuration object that has an array of FirewallRules
1
| public FirewallRule[] Rules { get; set; }
|
This rule is simply composed by four simple properties.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class FirewallRule
{
internal FirewallRule()
{
}
public FirewallRule(string name, int udpPort, int tcpPort, string secret)
{
Name = name;
UdpPort = udpPort;
TcpPort = tcpPort;
Secret = secret;
}
public String Name { get; set; }
public Int32 UdpPort { get; set; }
public Int32 TcpPort { get; set; }
public String Secret { get; set; }
}
|
Ok, nothing complex, now I’m expecting to being able to write this json configuration file to configure a single rule.
1
2
3
4
5
6
7
8
9
10
| {
"Rules" : [
{
"Name": "Rdp",
"UdpPort": 23456,
"TcpPort": 3389,
"Secret": "this_is_a_secret"
}
]
}
|
And being able to configure using standard Bind utilities of.NET configuration extensions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| const string testValue = @"
{
""Rules"" : [
{
""Name"": ""Rdp"",
""UdpPort"": 23456,
""TcpPort"": 3389,
""Secret"": ""this_is_a_secret""
}
]
}";
using var ms = new MemoryStream(Encoding.UTF8.GetBytes(testValue));
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonStream(ms)
.Build();
var config = new Configuration();
configuration.Bind(config);
|
Now I’m disappointed because the test fails because in Rules array I have only a single null element. It seems that Bind does not work perfectly with arrays or am I doing something wrong.
The solution was quite simple, I created a method inside the Configuration object that will allows binding from a standard.NET Core IConfiguration object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public void Bind(IConfiguration configuration)
{
configuration.Bind(this);
List<FirewallRule> rulesList = new List<FirewallRule>();
var rules = configuration.GetSection("Rules").GetChildren().ToList();
foreach (var rule in rules)
{
var firewallRule = new FirewallRule();
rule.Bind(firewallRule);
rulesList.Add(firewallRule);
}
Rules = rulesList.ToArray();
}
|
As you can see I explicitly get the section Rules, and for each child I explicitly created a FirewallRule and populate properties with standard Bind() method. And everything worked perfectly. I’am a little bit puzzled, because I suspect that I’m doing something wrong because base Bind() method should work out of the box, but at least with this fix all tests are still green.
Gian Maria.