I have a web request that is working properly, but it is just returning the status OK, but I need the object I am asking for it to return. I am not sure how to get the json value I am requesting. I am new to using the object HttpClient, is there a property I am missing out on? I really need the returning object. Thanks for any help
Making the call - runs fine returns the status OK.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMsg = client.GetAsync(string.Format("http://localhost:5057/api/Photo")).Result;
The api get method
//Cut out alot of code but you get the idea
public string Get()
{
return JsonConvert.SerializeObject(returnedPhoto);
}
If you are referring to the System.Net.HttpClient in .NET 4.5, you can get the content returned by GetAsync using the HttpResponseMessage.Content property as an HttpContent-derived object. You can then read the contents to a string using the HttpContent.ReadAsStringAsync method or as a stream using the ReadAsStreamAsync method.
The HttpClient class documentation includes this example:
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Building on #Panagiotis Kanavos' answer, here's a working method as example which will also return the response as an object instead of a string:
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // Nuget Package
public static async Task<object> PostCallAPI(string url, object jsonObject)
{
try
{
using (HttpClient client = new HttpClient())
{
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
if (response != null)
{
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<object>(jsonString);
}
}
}
catch (Exception ex)
{
myCustomLogger.LogException(ex);
}
return null;
}
Keep in mind that this is only an example and that you'd probably would like to use HttpClient as a shared instance instead of using it in a using-clause.
Install this nuget package from Microsoft System.Net.Http.Json. It contains extension methods.
Then add using System.Net.Http.Json
Now, you'll be able to see these methods:
So you can now do this:
await httpClient.GetFromJsonAsync<IList<WeatherForecast>>("weatherforecast");
Source: https://www.stevejgordon.co.uk/sending-and-receiving-json-using-httpclient-with-system-net-http-json
I think the shortest way is:
var client = new HttpClient();
string reqUrl = $"http://myhost.mydomain.com/api/products/{ProdId}";
var prodResp = await client.GetAsync(reqUrl);
if (!prodResp.IsSuccessStatusCode){
FailRequirement();
}
var prods = await prodResp.Content.ReadAsAsync<Products>();
What I normally do, similar to answer one:
var response = await httpClient.GetAsync(completeURL); // http://192.168.0.1:915/api/Controller/Object
if (response.IsSuccessStatusCode == true)
{
string res = await response.Content.ReadAsStringAsync();
var content = Json.Deserialize<Model>(res);
// do whatever you need with the JSON which is in 'content'
// ex: int id = content.Id;
Navigate();
return true;
}
else
{
await JSRuntime.Current.InvokeAsync<string>("alert", "Warning, the credentials you have entered are incorrect.");
return false;
}
Where 'model' is your C# model class.
It's working fine for me by the following way -
public async Task<object> TestMethod(TestModel model)
{
try
{
var apicallObject = new
{
Id= model.Id,
name= model.Name
};
if (apicallObject != null)
{
var bodyContent = JsonConvert.SerializeObject(apicallObject);
using (HttpClient client = new HttpClient())
{
var content = new StringContent(bodyContent.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Add("access-token", _token); // _token = access token
var response = await client.PostAsync(_url, content); // _url =api endpoint url
if (response != null)
{
var jsonString = await response.Content.ReadAsStringAsync();
try
{
var result = JsonConvert.DeserializeObject<TestModel2>(jsonString); // TestModel2 = deserialize object
}
catch (Exception e){
//msg
throw e;
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return null;
}
The code below is to access your HttpResponseMessage and extract your response from HttpContent.
string result = ret.Result.Content.ReadAsStringAsync().Result;
Convert your json in a structure according with your business
In my case BatchPDF is a complex object that it is being populated by result variable.
BatchPDF batchJson = JsonConvert.DeserializeObject<BatchPDF>(result);
return batchJson;
Related
The following is the code from where I would return a tuple of response status code and response output.
private Tuple<int, string> API_Check(string URL, string reqtype, string reqbody, string split_username, string split_pwd)
{
string responsetxt="";
HttpResponseMessage httpresult = new HttpResponseMessage();
int statuscode = 0;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
HttpClient _httpClient = new HttpClient();
var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes(split_username+":" + split_pwd));
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
try
{
using (var content = new StringContent(JsonConvert.SerializeObject(reqbody)))
{
if (reqtype == "GET")
{
httpresult = _httpClient.GetAsync(URL).Result;
}
if (reqtype == "PUT")
{
httpresult = _httpClient.PutAsync(URL, content).Result;
//httpresult = _httpClient.PutAsync()
}
if (reqtype == "POST")
{
httpresult = _httpClient.PostAsync(URL, content).Result;
}
statuscode = (int)httpresult.StatusCode;
responsetxt = httpresult.Content.ReadAsStringAsync().Result;
return Tuple.Create(statuscode, responsetxt);
}
}
catch (System.Net.WebException Excptn)
{
statuscode = 401;
responsetxt = Excptn.Status.ToString();
using (var stream = Excptn.Response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
MessageBox.Show(reader.ReadToEnd());
}
}
return Tuple.Create(statuscode, responsetxt);
}
For some reason, the request body is not getting filled correctly during the call. I'm getting 401 Unauthorized as for this Post call, which is definitely not a authorization error as the response message that I receive is equivalent to empty body or invalid input json format.
When I tried to hit the same reqbody for the endpoint with Postman, I'm getting 200 with valid response. Also, the GetAsync works for a similar API which doesn't require a body.
I verified there is no issues with the username, password or the Endpoint URL.
Is there a way, I could avoid using httpcontent and use the string as it is for hitting the API through C#?
Now, I could not use HttpWebRequest due to my current .Net framework limitations.
There are many issues with your code:
Primarily, you are serializing reqbody which is already a string. It sounds like you have a JSON string already, in which case you don't need to serialize it.
Don't use .Result, it can cause a deadlock. use await instead.
Use Valuetuples instead of Tuple, which can be inefficient.
Do not set ServicePointManager.SecurityProtocol = ..., instead let the operating system choose the best security protocol.
Do not use ServicePointManager in general, as it affects all HTTP request from your app. Instead set the relevant HtppClient property, or better: use HttpRequestMessage and set it directly on the message.
You can simplify the code a bit if you use HttpRequestMessage, giving it the type of HTTP method
You are catching the wrong exception type. You should be catching HttpRequestException, from which you can get the actual StatusCode.
HttpClient by default does not throw on non-success codes. You need to handle them explicitly.
Cache the HttpClient, or you could get socket exhaustion.
Creating a new HttpResponseMessage doesn't make a huge amount of sense.
HttpClient _httpClient = new HttpClient {
DefaultRequestHeaders = {
ExpectContinue = false,
},
};
private async Task<(int, string)> API_Check(string URL, HttpMethod reqtype, string reqbody, string split_username, string split_pwd)
{
var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes(split_username + ":" + split_pwd));
try
{
using (var content = new StringContent(reqbody))
using (var request = new HttpRequestMessage(URL, reqtype))
{
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
if (reqtype != "GET")
message.Content = content;
using var httpresult = await _httpClient.SendAsync(URL, content);
var statuscode = (int)httpresult.StatusCode;
var responsetxt = await httpresult.Content.ReadAsStringAsync();
if (!httpresult.IsSuccessStatusCode)
MessageBox.Show(responsetxt);
return (statuscode, responsetxt);
}
}
catch (HttpRequestException ex)
{
var statuscode = ex.StatusCode ?? 0;
var responsetxt = ex.Message;
MessageBox.Show(responsetxt);
return (statuscode, responsetxt);
}
}
If you actually have an object to serialize then change the method to
private async Task<(int, string)> API_Check(string URL, HttpMethod reqtype, object reqbody, string split_username, string split_pwd)
{
....
....
using (var content = new StringContent(JsonConvert.SerializeObject(reqbody)))
I have an API in .net 5 that runs locally. One of the endpoints is https://localhost:44362/User
Now, I created a console app that will consume the API and defined a method to call the get User.
public async Task<bool> CallAPI()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44362/");
using (HttpResponseMessage response = await client.GetAsync("User"))
{
var resContent = response.Content.ReadAsStringAsync().Result;
return true;
}
}
}
Here is the code in the API
[HttpGet]
public IEnumerable<User> Get()
{
using (var context = new ohabartContext())
{
return context.Users.ToList();
}
}
But when the code using (HttpResponseMessage response = await client.GetAsync("User")) is executed nothing happens. I don't receive any error or whatsoever. I search the net and all other codes look the same in consuming or calling an API.
What seems to be the problem?
ReadAsStringAsync() Serialize the HTTP content to a string as an asynchronous operation. This operation will not block. The returned Task object will complete after all of the content has been written as a string.
HttpResponseMessage response= await client.GetAsync(u);
var resContent = await response.Content.ReadAsStringAsync().Result;
Once the operation completes, the Result property on the returned task object contains the string with the HTTP content.
public async Task<bool> CallAPI()
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44362/");
HttpResponseMessage response = await client.GetAsync(u);
var resContent = awit response.Content.ReadAsStringAsync().Result;
return true;
}
}
catch (HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} " , e.Message);
return false;
}
}
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.getasync?view=net-6.0
I have this code for recovering Http code and description, but Visual Studio says that WebRequest is obsolete and that I have to use HttpClient. I'm not familiar with HttpClient can you help me?
IConfigurationRoot config;
myRequest = WebRequest.CreateHttp($"{config["BASE_URL"]}{link}");
myResponse = (HttpWebResponse)myRequest.GetResponse();
Check_load($"{config["BASE_URL"]}{link}");
var code = ((int)myResponse.StatusCode);
var desc = myResponse.StatusDescription;
var client = new HttpClient();
var response = await client.GetAsync(url);
var statusCode = response.StatusCode;
var content = response.Content;
if(statusCode != HttpStatusCode.OK && statusCode != HttpStatusCode.Created){
//return something, error, description
}
Update
From comment #Charlieface pointed out where I haven't declared HttpClient as static field. To avoid creating instances of HttpClient every time it is called, the complete workground as below.
public class HttpHelper{
private static HttpClent client = new HttpClient();
public static async Task<string> GetAsync(string url)
{
var response = await client.GetAsync(url);
var statusCode = response.StatusCode;
var content = response.Content;
if(statusCode != HttpStatusCode.OK && statusCode != HttpStatusCode.Created)
{
//return something, error, description
//return $"error with status code: {statusCode}";
}
else
{
//return "success";
}
}
}
The use of HttpClient is very simple. See the code below
try
{
using (HttpClient client = new HttpClient())
{
var res = await client.GetAsync(url);
var response = await res.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<MyObject>(response);
// use the new data retreived...
}
}
catch (Exception)
{
responseMessage = new BadRequestObjectResult("error retreiving data");
}
This suppose your data are sent in JSON format
I am invoking a third party POST API from my own API (again POST METHOD). The third party API is having a security key, and it is working fine on the POSTMAN tool. However, when I tries to invoke through code, I am getting error, 'Bad Gateway'. Following is the code which I tried.
public static async Task<string> GetDetailsfromThirdParty(string kszstrng)
{
string contentstring = string.Empty;
using (var client = new HttpClient())
{
string baseURL = "https://abcde.kz.in/b2/vhsearch-all";
string prms = kszstrng;// input parameters to API, in JSON Format- this is JSON String.
try
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Add("key", "value");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(prms);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(baseURL, content).ConfigureAwait(false);
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
contentstring = result;
}
}
catch (Exception ex)
{
string msg = ex.Message.ToString();
}
return contentstring;
}
}
I am getting error on this line:
var response = await httpClient.PostAsync(baseURL, content).ConfigureAwait(false);
While trying to execute I am getting the below error:
Not able to find out what's the issue? There is no network / Fireawall blockage. I have cross-verified with Systems Team as well.
Please suggest any issue with the code.
First of all, i recommend you to not declare the HttpClient in a using statement since this can cause a socket exhaustion (because the connections will stay open).
(see the docs for details)
Go for a static HttpClient (or use the IHttpClientFactory if you're project is .net Core).
I can't test your code since I'm not able to access this api.
But give it a try using a cleaner approach:
// static HttpClient
private static readonly HttpClient _HttpClient = new HttpClient();
// Can be used to set the baseUrl of the HttpClient from outside
public static void SetBaseUrl(Uri baseUrl)
{
_HttpClient.BaseAddress = baseUrl;
}
public static async Task<string> GetDetailsfromThirdParty(string kszstrng)
{
string contentstring = string.Empty;
string baseURL = "https://abcde.kz.in/b2/vhsearch-all";
string prms = kszstrng; // input parameters to API, in JSON Format- this is JSON String.
try
{
// Be aware of which headers you wanna clean if using the static HttpClient
_HttpClient.DefaultRequestHeaders.Accept.Clear();
_HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_HttpClient.DefaultRequestHeaders.Add("key", "value");
_HttpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
byte[] messageBytes = Encoding.UTF8.GetBytes(prms);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _HttpClient.PostAsync(baseURL, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
contentstring = result;
}
}
catch (Exception ex)
{
// your exception handling
}
return contentstring;
}
Issue resolved. While forming the object to JSON String, there was an opening and closing angle brackets ([,]). Even though this is coming automatically while converting to JSON string, this was not accepted string at the vendor end. So I removed it and works perfectly. Thanks every one for the support.
I'm trying to get API response by passing service url and json parameter. Url and Parameter passing properly to the requestAPI function, but doesn't give response from PostAsync method. Url is the API location, parameter is the Category Id. When I'm running same API in the browser, it gives correct response. But not in app.
This is requestAPI function.
public async Task<ResponseObject> requestAPI(string urlString, string jsonParameters)
{
await Task.Delay(2000); // NOTE: just to simulate a HTTP request over the wire
try
{
var json = JsonConvert.SerializeObject(jsonParameters);
HttpContent httpContent = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
if (true) // no issue here.
{
response = await client.PostAsync(urlString, httpContent);
}
else
{
response = await client.PutAsync(urlString, httpContent);
}
if (response.IsSuccessStatusCode)
{
Debug.WriteLine(#" TodoItem successfully saved.");
var returnVal = await response.Content.ReadAsStringAsync();
return new ResponseObject{
jsonString = returnVal,
isSuccess = true,
error = null
};
}
else
{
return new ResponseObject
{
jsonString = null,
isSuccess = false,
error = null
};
}
}
catch (Exception ex)
{
Debug.WriteLine(#" ERROR {0}", ex.Message);
return new ResponseObject
{
jsonString = null,
isSuccess = false,
error = null
};
}
}
Category Id comes from this method.
private async void loadBookList(string categoryId)
{
IsBusy = true;
if (CrossConnectivity.Current.IsConnected)
{
ResponseObject responseObject = await _apiService.requestAPI("http://192.168.0.35/kiyawamu-api/index.php/rest/V1/mobileappintegration/getbookdetailsbycategory", Convert.ToString(categoryId));
if (responseObject.isSuccess)
{
var jsonObject = JsonConvert.DeserializeObject<BookListJsonObject>(responseObject.jsonString);
CategoryBooks = new ObservableCollection<Book>(jsonObject.booksByCategory);
}
else
{
giveAlertForCommonError();
}
}
}
I tried following solutions, but doesn't work.
Url used as a uri var uri = new Uri(urlString);
jsonParameter also used as a string
GetAsync also used
Any assistance on this will be greatly appreciated.
If you're running it on Android and the code is in a PCL, try to add ModernHttpClient so you can use the native HttpClientHandler.
https://github.com/paulcbetts/ModernHttpClient
But I also recommend all to upgrade from PCL to .NET standard. If you do so you don't have to install a NuGet package to use HttpCliennt. And then you can select implementation of HttpClientHandler in project settings.