Reputation: 1286
I want to send a HTTP request that looks like this:
http://api.com/main?id=1234&id=5678
, the id will be GUID in string eventually.
I tried the below piece of code:
var idString = string.Join(",", listOfIds);
var queryString = new Dictionary<string, string>
{
{"id", idString}
};
requestUri = QueryHelpers.AddQueryString(requestUri, queryString);
This will give me like: http://api.com/main?id=1234,5678
but I want the style like above.
Is there anyway to achieve this without using for loop?
Upvotes: 1
Views: 2144
Reputation: 21526
This will give me like: http://api.com/main?id=1234,5678 but I want the style like above, e.g., http://api.com/main?id=1234&id=5678
I think the accept answer didn't address this issue from OP.
Using AddQueryString(string uri, IEnumerable<KeyValuePair<string, string>> queryString)
overload when you have an array you want to be part of the query string would only give you the comma-separated string as the parameter, and most of the time that is not what you want.
For example,
var endpoint = "v1/api/endpoint";
var arrayOfIds = new[] { "1", "2", "3" };
var queryString = new[]
{
new KeyValuePair<string,string>("id",new StringValues(arrayOfIds)),
new KeyValuePair<string,string>("other","value"),
...
};
var url = QueryHelpers.AddQueryString(endpoint, queryString);
The url at the end would look like (demo)
v1/api/endpoint?id=1,2,3&other=value
To get what OP wants, we will need to use the StringValues' overload AddQueryString(string uri, IEnumerable<KeyVaulePair<string, StringValues>> queryString)
.
For example,
var endpoint = "v1/api/endpoint";
var arrayOfIds = new[] { "1", "2", "3" };
var queryString = new []
{
new KeyValuePair<string, StringValues>("id", new StringValues(arrayOfIds)),
new KeyValuePair<string, StringValues>("other", "value")
};
var url = QueryHelpers.AddQueryString(endpoint, queryString);
Then the URL would look like (demo)
v1/api/endpoint?id=1&id=2&id=3&other=value
Just in case you wonder why you don't see the StringValues' overload, even you are running on .NET 5+?
Maybe you have multiple versions of .NET installed, and your app is still referencing the old version 2.*, which is marked as deprecated recently.
To make sure you use the latest .NET, in your .csproj file, you can add the framework reference like the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
...
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
...
</Project>
Upvotes: 0
Reputation: 131706
QueryHelpers doesn't work with arrays because there's no standard way to pass an array of values in a query string. Some applications accept id=1,2,3
others id=1&id=2&id=3
while others id[0]=1&id[1]=2&id[2]=3
.
.NET (Core) 5 and later
AddQueryString now works with lists of KeyValuePair<string,string>
or KeyValuePair<string,StringValues>
var parameters=new []{
new KeyValuePair<string,string>("id",new StringValues(arrayOfIds)),
new KeyValuePair<string,string>("other","value"),
...
};
var finalUri=QueryHelpers.AddQueryString(requestUri, parameters);
The StringValues constructors accept either a single string or an array of strings
Before .NET (Core) 5
String.Join
itself uses a loop and a StringBuilder to create a new string without allocating temporary strings. Strings are immutable, so any string modification operation results in a new temporary string.
You could use the source code as a guide to build your own loop. A quick solution could be something like this:
string ArrayToQueryString_DONT_USE(string name,string[] values)
{
var result=new StringBuilder();
result.AppendFormat("{0}={1}",name,value);
for(int i=1;i<values.Length;i++)
{
result.AppendFormat("&{0}={1}',name,values[i]);
}
return result.ToString();
}
Unfortunately, that won't work if the parameter names or values need encoding. That's what AddQueryString does, using, once again, a StringBuilder to avoid allocating temporary strings. We can borrow that code as well:
string ArrayToQueryString(string name,string[] values)
{
var result=new StringBuilder();
result.AppendFormat("{0}={1}",name,value);
for(int i=1;i<values.Length;i++)
{
result.Append('&');
result.Append(UrlEncoder.Default.Encode(name));
result.Append('=');
result.Append(UrlEncoder.Default.Encode(values[i]));
}
return result.ToString();
}
Upvotes: 4