Working in a C# Asp.netcore project, I'm trying to read an array from an IQueryCollection in a GET request. The IQueryCollection is in Request.Query.
I need to read the query without a model. When the front end json hits the back end, its no longer JSON which is fine, I just need to read whatever the front end passed. In this example its a int array but it could be anything.
Models don't scale very well for queries. To return a model on a get, they work brilliantly but for a query that can be as complex or simple as it needs to be I can't commit to models. Would be really usefull if I could extract the query to an anonamous object.
Json passed from the front end:
var params = {
items: [1, 4, 5],
startDate: new Date(),
endDate: new Date()
}
C# Request.QueryString
{?items%5B%5D=1&items%5B%5D=4&items%5B%5D=5&startDate=Fri%20Oct%2015%202021%2022%3A30%3A57%20GMT%2B1000%20(Australian%20Eastern%20Standard%20Time)&endDate=Fri%20Oct%2015%202021%2022%3A30%3A57%20GMT%2B1000%20(Australian%20Eastern%20Standard%20Time)}
I've tried:
// Gives me a null
var value = HttpUtility.ParseQueryString(Request.QueryString.Value).Get("items");
// Gives me an empty object {}
var value = Request.Query["items"];
Hope this is enough information.
CodePudding user response:
The query string format is undefined for arrays. Some web frameworks use ?foo[]=1&foo[]=2
, others use ?foo=1&foo=2
, again others ?foo[0]=1&foo[1]=2
.
You'll have to use the same parsing serverside as you serialize it clientside. This works for your []
syntax:
var queryString = "?items[]=1&items[]=4&items[]=5&date=2021-10-15";
var parsed = HttpUtility.ParseQueryString(queryString);
foreach (var key in parsed.AllKeys)
{
if (key.EndsWith("[]"))
{
var values = string.Join(", ", parsed.GetValues(key));
Console.WriteLine($"{key}: array: {values}.");
}
else
{
Console.WriteLine($"{key}: scalar: {parsed[key]}.");
}
}
Output:
items[]: array: 1, 4, 5.
date: scalar: 2021-10-15.
But instead of parsing the query string yourself, let the framework do that. You say you don't find models scalable; I find that hand-crafting code doesn't scale well. A model like this would just work, granted you fix your date serializer on the JS side:
public class RequestModel
{
public int[] Items { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}