Home > Net >  Escaping square brackets in dictionary keys passed via query string
Escaping square brackets in dictionary keys passed via query string

Time:05-02

I have an API action that accepts a dictionary from the query string like so:

[ApiController]
public class MyController : ControllerBase {
    public async Task<ActionResult> Post(CancellationToken ct, [FromQuery(Name = "responses")] Dictionary<string, bool> responses, [FromBody] MyModelType model) { }
}

The dictionary keys describe nested properties on model (which is sent as the request body), e.g.:

Foo
Foo.Bar
Bar[2].Foo

For the first two keys above, the dictionary binding works fine (as you would expect):

POST https://localhost/MyController?responses[Foo]=true&responses[Foo.Bar]=false

However, for the third key it fails due to the square brackets:

POST https://localhost/MyController?responses[Bar[2].Foo]=false

...with responses containing a single entry with the key Bar[2. Clearly the input needs to be escaped, but I haven't been able to find any documentation for how to do this, and the following approaches have not worked:

Bar\[2\].Foo
Bar[[2]].Foo

How should I go about escaping square brackets in the query string when binding to a dictionary?

CodePudding user response:

You can use the following request:

https://localhost/MyController?responses[0].key=bar[2].Foo&responses[0].value=false

Result:

enter image description here

For you use [FromQuery(Name = "responses")], so you must use responses[index].xxx.

CodePudding user response:

I believe there are two ways to solve this problem. First, you can bind a dictionary by treating it exactly the same as a List<KeyPair<,>>. Providing;

https://localhost/MyController?responses[0].key=Foo&responses[0].value=true&responses[1].key=bar[2].Foo&responses[1].value=false

Or, rather than numeric indices, you can provide all the index names explicitly;

https://localhost/MyController?responses.index=Foo&responses.index=bar[2].Foo&responses[Foo]=true&responses[bar[2].Foo]=false
  • Related