Build Query String for System.Net.Httpclient Get

Build query string for System.Net.HttpClient get

If I wish to submit a http get request using System.Net.HttpClient
there seems to be no api to add parameters, is this correct?

Yes.

Is there any simple api available to build the query string that
doesn't involve building a name value collection and url encoding
those and then finally concatenating them?

Sure:

var query = HttpUtility.ParseQueryString(string.Empty);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
string queryString = query.ToString();

will give you the expected result:

foo=bar%3c%3e%26-baz&bar=bazinga

You might also find the UriBuilder class useful:

var builder = new UriBuilder("http://example.com");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
builder.Query = query.ToString();
string url = builder.ToString();

will give you the expected result:

http://example.com/?foo=bar%3c%3e%26-baz&bar=bazinga

that you could more than safely feed to your HttpClient.GetAsync method.

.NET HttpClient add query string and JSON body to POST

I ended up finding Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString() that was what I needed. This allowed me to add the query string parameters without having to build the string manually (and worry about escaping characters and such).

Note: I'm using ASP.NET Core, but the same method is also available through Microsoft.Owin.Infrastructure.WebUtilities.AddQueryString()

New code:

// Query string parameters
var queryString = new Dictionary<string, string>()
{
{ "foo", "bar" }
};

// Create json for body
var content = new JObject(json);

// Create HttpClient
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.baseaddress.com/");

// This is the missing piece
var requestUri = QueryHelpers.AddQueryString("something", queryString);

var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
// Setup header(s)
request.Headers.Add("Accept", "application/json");
// Add body content
request.Content = new StringContent(
content.ToString(),
Encoding.UTF8,
"application/json"
);

// Send the request
client.SendAsync(request);

How can I add a query string into HttpClient.BaseAdress in c#?

I'd be tempted to use a DelegatingHandler if you need to apply an API key to every single request:

private class KeyHandler : DelegatingHandler
{
private readonly string _escapedKey;

public KeyHandler(string key) : this(new HttpClientHandler(), key)
{
}

public KeyHandler(HttpMessageHandler innerHandler, string key) : base(innerHandler)
{
// escape the key since it might contain invalid characters
_escapedKey = Uri.EscapeDataString(key);
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// we'll use the UriBuilder to parse and modify the url
var uriBuilder = new UriBuilder(request.RequestUri);

// when the query string is empty, we simply want to set the appid query parameter
if (string.IsNullOrEmpty(uriBuilder.Query))
{
uriBuilder.Query = $"appid={_escapedKey}";
}
// otherwise we want to append it
else
{
uriBuilder.Query = $"{uriBuilder.Query}&appid={_escapedKey}";
}
// replace the uri in the request object
request.RequestUri = uriBuilder.Uri;
// make the request as normal
return base.SendAsync(request, cancellationToken);
}
}

Usage:

httpClient = new HttpClient(new KeyHandler(Key));
httpClient.BaseAddress = new Uri($"https://api.openweathermap.org/data/2.5/weather");

// since the logic of adding/appending the appid is done based on what's in
// the query string, you can simply write `?q=mexico` here, instead of `&q=mexico`
using (var response = await ApiHelper.httpClient.GetAsync("?q=mexico"))

** Note: If you're using ASP.NET Core, you should call services.AddHttpClient() and then use IHttpHandlerFactory to generate the inner handler for KeyHandler.

HttpClient GetAsync with query string

Ciao, the problem is related with key parameter on URL. Change your code like this:

using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/");

using (HttpResponseMessage response = await client.GetAsync("geocode/json?address=1400,Copenhagen,DK&key=" + GoogleMapsAPIkey))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}

As google sheets said:

After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs. The API key is safe for embedding in URLs; it doesn't need any encoding.

Parameterized query with c # HttpClient

What exactly do you mean by "you have to send the variable as a parameter"? Does it mean you want to add parameters dynamically by number and name?
In this case you could have e.g. a Dictionary as input and convert it into a query string:

var queryParameters = new Dictionary<string, string>
{
{ "business_code", "123" },
{ "someOtherParam", "456"}
};
var dictFormUrlEncoded = new FormUrlEncodedContent(queryParameters);
var queryString = await dictFormUrlEncoded.ReadAsStringAsync();

var response = await _client.GetAsync($"users?{queryString}")

How to build a query string for a URL in C#?

If you look under the hood the QueryString property is a NameValueCollection. When I've done similar things I've usually been interested in serialising AND deserialising so my suggestion is to build a NameValueCollection up and then pass to:

using System.Linq;
using System.Web;
using System.Collections.Specialized;

private string ToQueryString(NameValueCollection nvc)
{
var array = (
from key in nvc.AllKeys
from value in nvc.GetValues(key)
select string.Format(
"{0}={1}",
HttpUtility.UrlEncode(key),
HttpUtility.UrlEncode(value))
).ToArray();
return "?" + string.Join("&", array);
}

I imagine there's a super elegant way to do this in LINQ too...

Is there a simple way to format query strings when using the .NET HttpClient class?

You might want to consider using UriTemplates to construct Uris. The syntax is specified in RFC6570. I wrote a library that has a nuget package here.

With UriTemplates you can not only fill in query parameters like,

    [Fact]
public void ShouldAllowUriTemplateWithQueryParamsWithOneValue()
{
var template = new UriTemplate("http://example.org/foo{?bar,baz}");
template.SetParameter("baz", "yo");


var uriString = template.Resolve();
Assert.Equal("http://example.org/foo?baz=yo", uriString);
}

Don't worry if you don't supply a query string parameter, the token will be removed.

It also handles path parameters,

    [Fact]
public void ShouldAllowUriTemplateWithMultiplePathSegmentParameter()
{
var template = new UriTemplate("http://example.org/foo/{bar}/baz/{blar}");
template.SetParameter("bar", "yo");
template.SetParameter("blar", "yuck");
var uriString = template.Resolve();
Assert.Equal("http://example.org/foo/yo/baz/yuck", uriString);
}

and some really nifty stuff with parameters that are lists and dictionaries,

    [Fact]
public void ShouldAllowListAndSingleValueInQueryParam()
{
var template = new UriTemplate("http://example.org{/id*}{?fields,token}");
template.SetParameter("id", new List<string>() { "person", "albums" });
template.SetParameter("fields", new List<string>() { "id", "name", "picture" });
template.SetParameter("token", "12345");
var uriString = template.Resolve();
Assert.Equal("http://example.org/person/albums?fields=id,name,picture&token=12345", uriString);
}

and it will handle all sorts of tricky URI encoding issues,

    [Fact]
public void ShouldHandleUriEncoding()
{
var template = new UriTemplate("http://example.org/sparql{?query}");
template.SetParameter("query", "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }");
var uriString = template.Resolve();
Assert.Equal("http://example.org/sparql?query=PREFIX%20dc%3A%20%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%3E%20SELECT%20%3Fbook%20%3Fwho%20WHERE%20%7B%20%3Fbook%20dc%3Acreator%20%3Fwho%20%7D", uriString);
}


[Fact]
public void ShouldHandleEncodingAParameterThatIsAUriWithAUriParameter()
{
var template = new UriTemplate("http://example.org/go{?uri}");
template.SetParameter("uri", "http://example.org/?uri=http%3A%2F%2Fexample.org%2F");
var uriString = template.Resolve();
Assert.Equal("http://example.org/go?uri=http%3A%2F%2Fexample.org%2F%3Furi%3Dhttp%253A%252F%252Fexample.org%252F", uriString);
}

The only item that still is not working is encoding double byte Unicode characters in URIs. There is also a preview release that is PCL library allow you to use it in WinRT and on Windows Phone.



Related Topics



Leave a reply



Submit