HttpClient GetAsync with query string - c#

I am using Google's GeoCoding API. I have two methods where one works and the other doesn't and I can't seem to figure out why:
string address = "1400,Copenhagen,DK";
string GoogleMapsAPIurl = "https://maps.googleapis.com/maps/api/geocode/json?address={0}&key={1}";
string GoogleMapsAPIkey = "MYSECRETAPIKEY";
string requestUri = string.Format(GoogleMapsAPIurl, address.Trim(), GoogleMapsAPIkey);
// Works fine
using (var client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(requestUri))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}
// Doesn't work
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/", UriKind.Absolute);
client.DefaultRequestHeaders.Add("key", GoogleMapsAPIkey);
using (HttpResponseMessage response = await client.GetAsync("geocode/json?address=1400,Copenhagen,DK"))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
}
}
My last method with GetAsync where I am sending a query string doesn't work and I am in doubt why it is so. When I introduce BaseAddress on the client the GetAsync somehow doesn't send to the correct URL.

I don't suggest adding API key into globals. Maybe you'll need to send some HTTP request outside of the API and the key will be leaked.
Here's the example that works.
using Newtonsoft.Json;
public class Program
{
private static readonly HttpClient client = new HttpClient();
private const string GoogleMapsAPIkey = "MYSECRETAPIKEY";
static async Task Main(string[] args)
{
client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/");
try
{
Dictionary<string, string> query = new Dictionary<string, string>();
query.Add("address", "1400,Copenhagen,DK");
dynamic response = await GetAPIResponseAsync<dynamic>("geocode/json", query);
Console.WriteLine(response.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
private static async Task<string> ParamsToStringAsync(Dictionary<string, string> urlParams)
{
using (HttpContent content = new FormUrlEncodedContent(urlParams))
return await content.ReadAsStringAsync();
}
private static async Task<T> GetAPIResponseAsync<T>(string path, Dictionary<string, string> urlParams)
{
urlParams.Add("key", GoogleMapsAPIkey);
string query = await ParamsToStringAsync(urlParams);
using (HttpResponseMessage response = await client.GetAsync(path + "?" + query, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
string responseText = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseText);
}
}
}

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.

Related

How to pass request content with HttpClient GetAsync method in c#

How do I pass request content in the HttpClient.GetAsync method? I need to fetch data depending upon request content.
[HttpGet]
public async Task<HttpResponseMessage> QuickSearch()
{
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response =await client.GetAsync("http://localhost:8080/document/quicksearch");
if (response.IsSuccessStatusCode)
{
Console.Write("Success");
}
If you are using .NET Core, the standard HttpClient can do this out-of-the-box. For example, to send a GET request with a JSON body:
HttpClient client = ...
...
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("some url"),
Content = new StringContent("some json", Encoding.UTF8, ContentType.Json),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
If you want to send content, then you need to send it as query string (According to your API route)
HttpResponseMessage response =await client.GetAsync("http://localhost:8080/document/quicksearch/paramname=<dynamicName>&paramValue=<dynamicValue>");
And in API check for "paramName" and "paramValue"
this works for me:
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("your url"),
Content = new StringContent("your json", Encoding.UTF8, ContentType.Json),
};
using (var response = await httpClient.SendAsync(request))
{
string apiResponse = await response.Content.ReadAsStringAsync();
}
}
EDITED:
This is minor different then #SonaliJain answer above:
MediaTypeNames.Application.Json instead of ContentType.Json
I'm assuming that your "request content" would be POST data, no?
If you're sending it using the standard form content way of doing it, you would first have to build the content:
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", "theperplexedone"),
new KeyValuePair<string, string>("password", "mypassword123"),
});
And then submit it using PostAsync instead:
var response = await client.PostAsync("http://localhost:8080/document/quicksearch", content);
Hi all thank you for your comments, i got the solution
[HttpGet]
public async Task<HttpResponseMessage> QuickSearch(HttpRequestMessage Query)
{
Debugger.Launch();
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
Console.WriteLine(Query);
HttpResponseMessage response = await client.GetAsync("http://localhost:8080/document/quicksearch/"+ Query.RequestUri.Query);
if (response.IsSuccessStatusCode)
{
Console.Write("Success");
}
else
{
Console.Write("Failure");
}
return response;
}
}
catch (Exception e)
{
throw e;
}

Unable to send string as HTTPContent

I have created an API, which shall have the capability to connect to en external API via POST and with a request body in form of a string.
I am able to connect directly to the API from Postman without trouble.. But it does not work via my own API.
Any ideas?
This is the Pastebin.
private string EncodeExternalApiLink = "https://blabla.dk";
private string EncodeExternalApiLinkPostFilter = "searchstring/blabla/api/search";
[HttpPost("getdata/filtered")]
public async Task<IActionResult> GetDataFromExternalFiltered([FromBody] string filter)
{
var filterString = new StringContent(filter);
EncodeExternalToken token = GetExternalToken().Result;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(EncodeExternalApiLink);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
using (var response = await client.PostAsync(EncodeExternalApiLinkPostFilter, filterString))
{
return Json(response);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
return Content(content, "application/json");
}
else
{
return NotFound();
}
}
}
}
Salutations. You might need to add a "/" to the end of your base address EncodeExternalApiLink or to the beginning of EncodeExternalApiLinkPostFilter.

why is this vsts rest api returning 404?

I was following this example to use the VSTS REST API:
https://learn.microsoft.com/en-us/rest/api/vsts/search/code%20search%20results/fetch%20code%20search%20results?view=vsts-rest-4.1
The following url points directly to MyService.MyController in my org's VSTS:
https://my-corp.visualstudio.com/DefaultCollection/USOpsInfrastructure/USOpsInfrastructure%20Team/_git/MyService?path=%2FMyService.UI%2FControllers%2FMyController.cs&version=GBmaster
I tried to follow the example code with my implentation code below but a 404 response is returned without a detailed message. Any idea what the issue might be or how to debug?
private static async Task FindMyControllerRefs()
{
var baseUrl = "https://my-corp.almsearch.visualstudio.com";
using (var client = GetHttpClient(baseUrl))
{
var request = "{ \"searchText\": \"MyController\" }";
var projectUri = "/USOpsInfrastructure/USOpsInfrastructure%20Team/_git/MyService";
var searchUri = "/_apis/search/codesearchresults?api-version=4.1-preview.1";
var fullUri = projectUri + searchUri;
var response = await client.PostAsJsonAsync(fullUri, request);
//process the response
if (response.IsSuccessStatusCode)
{
var result = (await response.Content.ReadAsAsync<string>());
}
else //not 200
{
var message = await response.Content.ReadAsStringAsync();
}
}
}
private static HttpClient GetHttpClient(string baseUrl)
{
var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new Uri(baseUrl);
client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
The Code search REST API should be :
POST https://XXX.almsearch.visualstudio.com/{Project}/_apis/search/codesearchresults?api-version=4.1-preview.1
In you scenario please confirm what's the team project name: USOpsInfrastructure or MyService. If you are not sure about that, then you can have a try for each of them.
Besides, base on my test you need to add the "$top": 10 (you can change the number as needed) in the request body:
var request = "{ \"searchText\": \"MyController\",\"$top\": 10 }";
Below code works on my side: (Project name is "Git" in below sample)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace CodeSearch
{
class Program
{
public static void Main()
{
Task t = CodeSearch();
Task.WaitAll(new Task[] { t });
}
private static async Task CodeSearch()
{
try
{
var username = "username";
var password = "Password/PAT";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
string url = "https://{instance}.almsearch.visualstudio.com/Git/_apis/search/codesearchresults?api-version=4.1-preview.1";
var content = new StringContent("{\"searchText\": \"OwinStartupAttribute\", \"$top\": 10}", Encoding.UTF8, "application/json");
using (HttpResponseMessage response = client.PostAsync(url, content).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Console.ReadLine();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}

POST Request UWP

I writing UWP app.
I need to send POST request with json to server
Here is my code for downloading JSON and writing to value:
public async void AllOrders_down()
{
string url = "http://api.simplegames.com.ua/index.php/?wc_orders=all_orders";
var json = await FetchAsync(url);
List<RootObject> rootObjectData = JsonConvert.DeserializeObject<List<RootObject>>(json);
OrdersList = new List<RootObject>(rootObjectData);
}
public async Task<string> FetchAsync(string url)
{
string jsonString;
using (var httpClient = new System.Net.Http.HttpClient())
{
var stream = await httpClient.GetStreamAsync(url);
StreamReader reader = new StreamReader(stream);
jsonString = reader.ReadToEnd();
}
return jsonString;
}
How I need to send POST request with this json to server?
Thank's for help.
Here is an example Post request that I have used in a UWP application.
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"http://test.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/api/testendpoint";
try
{
HttpContent content = new StringContent(JsonConvert.SerializeObject(yourPocoHere), Encoding.UTF8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(endpoint, content);
if (response.IsSuccessStatusCode)
{
string jsonResponse = await response.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception)
{
//Could not connect to server
//Use more specific exception handling, this is just an example
}
}
You should be using httpClient.PostAsync().

C#: Error when HttpClient reponse

I am doing HTTP get request using HttpClient in C# console app . I am not getting expected response with one get request.
Get Request is like
http://example.com/xyz/SearchProduct?productNo=11210&1d6rstc9xc=5jyi27htzk
I am getting some vague response but when i do same get request with fiddler it is giving expected response.
How can I get expected response from httpClient.GetAsync(url)?
code is :-
var httpClient = new HttpClient();
var url = "http://example.com/xyz/SearchProduct?productNo=11210&1d6rstc9xc=5jyi27htzk";
HttpResponseMessage response1 = await httpClient.GetAsync(url);
if (response1.IsSuccessStatusCode)
{
HttpContent stream = response1.Content;
Task<string> data = stream.ReadAsStringAsync();
}
You should read as string that way:
string result = await stream.ReadAsStringAsync();
instead of that:
Task<string> data = stream.ReadAsStringAsync();
Here full code example and another example
This is a full method using async/await approach.
private static async Task<string> GetRequestContentAsString(string url)
{
var data = string.Empty;
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var stream = response.Content;
data = await stream.ReadAsStringAsync();
}
}
return data;
}
This method is called this way:
var content = await GetRequestContentAsString("http://www.bing.com");

Categories

Resources