Dictionaries were missing

alphons <alphons@heijden.com> 21 Jan 2026, 17:55
1b5be32f1d9d23599fcf708fda68b27511225fae
6 files changed
  • JsonBodyProvider/JsonBodyValueProvider.cs
  • JsonBodyProvider/JsonBodyValueProviderFactory.cs
  • JsonBodyProviderTest/Controllers/FirstController.cs
  • JsonBodyProviderTest/JsonBodyProviderMulti.http
  • JsonBodyProviderTest/JsonBodyProviderTest.http
  • JsonBodyProviderTest/Program.cs
diff --git a/JsonBodyProvider/JsonBodyValueProvider.cs b/JsonBodyProvider/JsonBodyValueProvider.cs
index 13f8152..2f4eebc 100644
--- a/JsonBodyProvider/JsonBodyValueProvider.cs
+++ b/JsonBodyProvider/JsonBodyValueProvider.cs
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.ModelBinding;
+using System.Diagnostics;
using System.Globalization;
using System.Text.Json.Nodes;
@@ -10,27 +11,81 @@ internal class JsonBodyValueProvider(Dictionary<string, JsonNode?> values) : IVa
public ValueProviderResult GetValue(string key)
{
- if (!values.TryGetValue(key, out JsonNode? node) || node is null)
+ // 1. Exact match for scalar or array
+ if (values.TryGetValue(key, out JsonNode? node) && node is not null)
{
- return ValueProviderResult.None;
+ return ConvertToValueProviderResult(node);
}
- if (node is JsonArray array)
+ // 2. Handle dictionary index-based binding (e.g. "Properties[0].Key", "Properties[0].Value", "Properties.index")
+ if (key.Contains('[') && key.Contains(']'))
{
- string?[] valuesAsStrings = [.. array.Select(item => item?.ToString())];
+ int openIndex = key.IndexOf('[');
+ int closeIndex = key.IndexOf(']', openIndex);
+
+ if (closeIndex > openIndex)
+ {
+ string propertyName = key[..openIndex];
+ string indexStr = key[(openIndex + 1)..closeIndex];
+ string subProperty = key[(closeIndex + 1)..];
+
+ if (values.TryGetValue(propertyName, out JsonNode? dictNode) &&
+ dictNode is JsonObject dictObj)
+ {
+ var kvList = dictObj.ToList(); // Preserve JSON order
+
+ // Handle "prefix.index" → return indices as array ["0", "1", ...]
+ if (subProperty == ".index")
+ {
+ if (kvList.Count == 0)
+ return ValueProviderResult.None;
+ string[] indices = Enumerable.Range(0, kvList.Count)
+ .Select(i => i.ToString())
+ .ToArray();
+
+ return new ValueProviderResult(indices, CultureInfo.InvariantCulture);
+ }
+
+ // Handle "prefix[index].Key" or ".Value"
+ if (subProperty.StartsWith(".") &&
+ int.TryParse(indexStr, out int index) &&
+ index >= 0 && index < kvList.Count)
+ {
+ var kv = kvList[index];
+
+ if (subProperty == ".Key")
+ return new ValueProviderResult(kv.Key, CultureInfo.InvariantCulture);
+
+ if (subProperty == ".Value")
+ return new ValueProviderResult(kv.Value?.ToString() ?? string.Empty, CultureInfo.InvariantCulture);
+ }
+ }
+ }
+ }
+ return ValueProviderResult.None;
+ }
+
+ private static ValueProviderResult ConvertToValueProviderResult(JsonNode node)
+ {
+ if (node is JsonArray array)
+ {
+ string?[] valuesAsStrings = array.Select(item => item?.ToString()).ToArray()!;
return new ValueProviderResult(valuesAsStrings, CultureInfo.InvariantCulture);
}
- // Scalar gevallen
+ // Dictionaries: return None so binder uses index-based binding
+ if (node is JsonObject)
+ {
+ return ValueProviderResult.None;
+ }
+
string? rawValue = node switch
{
JsonValue valueNode when valueNode.TryGetValue(out object? obj) => obj?.ToString(),
- _ => node.ToJsonString() // object of fallback
+ _ => node.ToJsonString()
};
- return new ValueProviderResult(
- rawValue ?? string.Empty,
- CultureInfo.InvariantCulture);
+ return new ValueProviderResult(rawValue ?? string.Empty, CultureInfo.InvariantCulture);
}
}
\ No newline at end of file
diff --git a/JsonBodyProvider/JsonBodyValueProviderFactory.cs b/JsonBodyProvider/JsonBodyValueProviderFactory.cs
index 27822d0..d6bf3da 100644
--- a/JsonBodyProvider/JsonBodyValueProviderFactory.cs
+++ b/JsonBodyProvider/JsonBodyValueProviderFactory.cs
@@ -39,7 +39,6 @@ internal class JsonBodyValueProviderFactory : IValueProviderFactory
values.TryAdd(cookie.Key, JsonValue.Create(cookie.Value));
context.ValueProviders.Add(new JsonBodyValueProvider(values));
-
}
private static bool IsJsonContentType(HttpRequest request) =>
diff --git a/JsonBodyProviderTest/Controllers/FirstController.cs b/JsonBodyProviderTest/Controllers/FirstController.cs
index 834fe37..941f40f 100644
--- a/JsonBodyProviderTest/Controllers/FirstController.cs
+++ b/JsonBodyProviderTest/Controllers/FirstController.cs
@@ -6,12 +6,39 @@ namespace JsonBodyProviderTest.Controllers;
public class FirstController : ControllerBase
{
[HttpPost("Test")]
- public IActionResult Test(string name, int age)
+ public IActionResult Test(string Name, int age)
{
return Ok(new
{
- Name = $"Your name {name}",
+ Name = $"Your name {Name}",
Age = $"Your age {age}"
});
}
+
+
+ [HttpPost("Multi")]
+ public IActionResult MultiTest(
+ string EventName,
+ string UserId,
+ DateTime Timestamp,
+ int Value,
+ double Weight,
+ List<int> IntList,
+ Dictionary<string, string> Properties,
+ bool isConversion,
+ Guid? campaignId)
+ {
+ return Ok(new
+ {
+ EventName,
+ UserId,
+ Timestamp,
+ Value,
+ Weight,
+ IntList,
+ Properties,
+ isConversion,
+ campaignId
+ });
+ }
}
diff --git a/JsonBodyProviderTest/JsonBodyProviderMulti.http b/JsonBodyProviderTest/JsonBodyProviderMulti.http
new file mode 100644
index 0000000..988c103
--- /dev/null
+++ b/JsonBodyProviderTest/JsonBodyProviderMulti.http
@@ -0,0 +1,20 @@
+@JsonBodyProviderTest_HostAddress = http://localhost:5129
+
+POST {{JsonBodyProviderTest_HostAddress}}/First/Multi
+Content-Type: application/json
+
+{
+ "EventName": "Alphons",
+ "UserId": "alphons",
+ "Timestamp" : "2025-06-18T14:22:09Z",
+ "Value": 1,
+ "Weight": 123.4567,
+ "IntList": [ 1, 2, 3],
+ "Properties": {
+ "category": "electronics",
+ "source": "newsletter"
+ },
+ "isConversion": true,
+ "campaignId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
+}
+
diff --git a/JsonBodyProviderTest/JsonBodyProviderTest.http b/JsonBodyProviderTest/JsonBodyProviderTest.http
index 48630b1..0775a3a 100644
--- a/JsonBodyProviderTest/JsonBodyProviderTest.http
+++ b/JsonBodyProviderTest/JsonBodyProviderTest.http
@@ -4,6 +4,6 @@ POST {{JsonBodyProviderTest_HostAddress}}/First/Test
Content-Type: application/json
{
- "name": "Alphons",
+ "Name": "Alphons",
"age": 21
}
diff --git a/JsonBodyProviderTest/Program.cs b/JsonBodyProviderTest/Program.cs
index e2bc3c1..61d5d05 100644
--- a/JsonBodyProviderTest/Program.cs
+++ b/JsonBodyProviderTest/Program.cs
@@ -3,7 +3,7 @@ using JsonBodyProvider;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
-builder.Services.AddJsonProviders(CorrectLists: false);
+builder.Services.AddJsonProviders(CorrectLists: true);
var app = builder.Build();