Search code examples
c#.netapi

Any way to add arrays into HTTP request URI by using C#?


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?

Thanks!


Solution

  • 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();
    }