I have designed the following method to call api within the loop. I was wondering if there is any other better way (performance) of calling APIs multiple times?
private List<ClientInfo> populateDetails(List<ClientInfo> lstClientDetails)
{
using (var client = new HttpClient())
{
client.BaseAddress = EndpointAddress;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string Uri = "";
ClientInfo clientInfo;
foreach (var record in lstClientDetails)
{
Uri = string.Format("{0}", record.id);
var postResponse = client.GetAsync(Uri).Result;
if (postResponse.IsSuccessStatusCode)
{
string result = postResponse.Content.ReadAsStringAsync().Result;
clientInfo = JsonConvert.DeserializeObject<ClientInfo>(result);
if (clientInfo != null)
record.email = clientInfo.email;
}
}
return lstClientDetails;
}
}
Maybe you can change your code to use async/await pattern
private async Task populateDetails(List<ClientInfo> lstClientDetails)
{
using (var client = new HttpClient())
{
client.BaseAddress = EndpointAddress;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string Uri = "";
ClientInfo clientInfo;
foreach (var record in lstClientDetails)
{
Uri = string.Format("{0}", record.id);
var postResponse = await client.GetAsync(Uri);
if (postResponse.IsSuccessStatusCode)
{
string result = await postResponse.Content.ReadAsStringAsync();
clientInfo = JsonConvert.DeserializeObject<ClientInfo>(result);
if (clientInfo != null)
record.email = clientInfo.email;
}
}
}
}
And as you can see it doesn't make senso to return the same List which is passed as a paramters: the code will change the underlyne objects
Reference Microsoft Docs Parallel Library
sample code:
public class ParallelClient
{
private async Task ParallelRequest(List<string> requests)
{
var responses = new ConcurrentBag<HttpResponseMessage>();
using (var client = new HttpClient())
{
Parallel.ForEach(requests, new ParallelOptions { MaxDegreeOfParallelism = 10 }, async r =>
{
var requestMessage = new HttpRequestMessage();
requestMessage.Method = HttpMethod.Post;
requestMessage.Content = new StringContent(r, Encoding.UTF8, "application/json");
var response = await client.SendAsync(requestMessage);
responses.Add(response);
});
}
}
}
Related
public static async Task<HttpResponseMessage> Post(string endPoint, string data){
HttpContent c = new StringContent(data, Encoding.UTF8, "application/json");
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(VodapayBaseUrl + endPoint),
Content = c,
};
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.SendAsync(request).ConfigureAwait(false); // The code fails here
if (result.IsSuccessStatusCode)
{
Console.WriteLine("got here");
return result;
}
else
{
Console.WriteLine("failled");
return result;
}
}
// return result;
}
Here is an updated version:
public static async Task Post()
{
using (var httpClient = new HttpClient())
{
var requestString = "{\"authCode\": \"0000000001Nk1EEhZ3pZ73z700271891\" }";
httpClient.BaseAddress = new Uri("https://bounties-backend-mini-program.herokuapp.com");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/userInfo");
request.Content = new StringContent(requestString, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.SerializeObject(response.Headers.ToList()));
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Successful");
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine("Not successful");
}
}
}
class Program
{
private static void Main(string[] args)
{
Post().Wait();
Console.WriteLine();
}
}
}
Can someone please help with this I am new to c# and relatively new to coding. I am trying to send a request using httpclient I need to send data in a json format I also need to send a list of headers. How can I do this and also return json data at the end your help will be appreciated.I am getting an error when i run this:
Your code isn't far off, here's an example that I had in one of my projects ...
using (var httpClient = new HttpClient())
{
var requestString = "{\"authCode\": \"0000000001Nk1EEhZ3pZ73z700271891\" }";
// Setup the HttpClient and make the call and get the relevant data.
httpClient.BaseAddress = new Uri("https://bounties-backend-mini-program.herokuapp.com");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, $"/api/userInfo");
request.Content = new StringContent(requestString, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(JsonConvert.SerializeObject(response.Headers.ToList()));
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Successful");
Console.WriteLine(responseContent);
}
else
{
Console.WriteLine("Not successful");
}
}
... obviously, it has varying degrees of thought for the scenario at hand but just adapt it as need be.
I have uploaded a file to SharePoint and found out what id it has. Now I need to update some of the other columns on that listitem. The problem is that System.Net.Http.HttpMethod.Patch doesn't exist.
public static async Task<string> UpdateFileData()
{
var (authResult, message) = await Authentication.AquireTokenAsync();
string updateurl = MainPage.rooturl + "lists/edd49389-7edb-41db-80bd-c8493234eafa/items/" + fileID + "/";
var httpClient = new HttpClient();
HttpResponseMessage response;
try
{
var root = new
{
fields = new Dictionary<string, string>
{
{ "IBX", App.IBX }, //column to update
{ "Year", App.Year}, //column to update
{ "Month", App.Month} //column to update
}
};
var s = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
var content = JsonConvert.SerializeObject(root, s);
var request = new HttpRequestMessage(HttpMethod.Put, updateurl);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
catch (Exception ex)
{
return ex.ToString();
}
}
Modify the code as below.
public static async Task<string> UpdateFileData()
{
var (authResult, message) = await Authentication.AquireTokenAsync();
string updateurl = MainPage.rooturl + "lists/edd49389-7edb-41db-80bd-c8493234eafa/items/" + fileID + "/";
var httpClient = new HttpClient();
HttpResponseMessage response;
try
{
var root = new
{
fields = new Dictionary<string, string>
{
{ "IBX", App.IBX }, //column to update
{ "Year", App.Year}, //column to update
{ "Month", App.Month} //column to update
}
};
var s = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
var content = JsonConvert.SerializeObject(root, s);
var request = new HttpRequestMessage(new HttpMethod("PATCH"), updateurl);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
request.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/json;odata=verbose");
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
catch (Exception ex)
{
return ex.ToString();
}
}
Or we can also use REST API to update list item by ID.
Refer to: SharePoint 2013 REST Services using C# and the HttpClient
It dependents whether .NET Core or .NET Framework is utilized, in case of `.NET Core HttpClient.PatchAsync Method could be utilized.
In case of .NET Framework ListItem could be updated like this:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.BaseAddress = new Uri("https://graph.microsoft.com");
var listItemPayload = new Dictionary<string, object>
{
{"Color", "Fuchsia"},
{"Quantity", 934}
};
var requestContent = new StringContent(JsonConvert.SerializeObject(listItemPayload));
requestContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await client.PatchAsync(new Uri($"https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/items/{itemId}/fields"), requestContent);
var data = response.Content.ReadAsStringAsync().Result.ToString();
}
where PatchAsync is the extension method for HttpClient class:
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri requestUri, HttpContent iContent)
{
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, requestUri)
{
Content = iContent
};
HttpResponseMessage response = new HttpResponseMessage();
try
{
response = await client.SendAsync(request);
}
catch (TaskCanceledException e)
{
Debug.WriteLine("ERROR: " + e.ToString());
}
return response;
}
}
All the credits for extension method go to the author of this answer
Can't you just use the HttpMethod class constructor?
new HttpMethod("PATCH");
Source: https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpmethod.-ctor?view=netframework-4.7.2#System_Net_Http_HttpMethod__ctor_System_String_
I need to postAsync with header and content together. In order to get access to a website through Console Application in C#. I have my headers as an HttpHeader object with variable name header and my content named newContent as a string object with __Token, return, Email and Password. Now what I want to do is add newContent to header and then use postAsync(url, header+content) to make my POST request.
public async static void DownloadPage(string url)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (HttpClient client = new HttpClient(handler))
{
using (HttpResponseMessage response = client.GetAsync(url).Result)
{
//statusCode
CheckStatusCode(response);
//header
HttpHeaders headers = response.Headers;
//content
HttpContent content = response.Content;
//getRequestVerificationToken&createCollection
string newcontent = CreateCollection(content);
using(HttpResponseMessage response2 = client.PostAsync(url,))
}
}
}
public static string GenerateQueryString(NameValueCollection collection)
{
var array = (from key in collection.AllKeys
from value in collection.GetValues(key)
select string.Format("{0}={1}", WebUtility.UrlEncode(key), WebUtility.UrlEncode(value))).ToArray();
return string.Join("&", array);
}
public static void CheckStatusCode(HttpResponseMessage response)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.ReasonPhrase));
else
Console.WriteLine("200");
}
public static string CreateCollection(HttpContent content)
{
var myContent = content.ReadAsStringAsync().Result;
HtmlNode.ElementsFlags.Remove("form");
string html = myContent;
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var input = doc.DocumentNode.SelectSingleNode("//*[#name='__Token']");
var token = input.Attributes["value"].Value;
//add all necessary component to collection
NameValueCollection collection = new NameValueCollection();
collection.Add("__Token", token);
collection.Add("return", "");
collection.Add("Email", "11111111#hotmail.com");
collection.Add("Password", "1234");
var newCollection = GenerateQueryString(collection);
return newCollection;
}
I did the very same thing yesterday. I created a seperate class for my Console App and put the HttpClient stuff in there.
In Main:
_httpCode = theClient.Post(_response, theClient.auth_bearer_token);
In the class:
public long Post_RedeemVoucher(Response _response, string token)
{
string client_URL_voucher_redeem = "https://myurl";
string body = "mypostBody";
Task<Response> content = Post(null, client_URL_voucher_redeem, token, body);
if (content.Exception == null)
{
return 200;
}
else
return -1;
}
Then the call itself:
async Task<Response> Post(string headers, string URL, string token, string body)
{
Response _response = new Response();
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
using (HttpResponseMessage response = await client.SendAsync(request))
{
if (!response.IsSuccessStatusCode)
{
_response.error = response.ReasonPhrase;
_response.statusCode = response.StatusCode;
return _response;
}
_response.statusCode = response.StatusCode;
_response.httpCode = (long)response.StatusCode;
using (HttpContent content = response.Content)
{
_response.JSON = await content.ReadAsStringAsync().ConfigureAwait(false);
return _response;
}
}
}
}
catch (Exception ex)
{
_response.ex = ex;
return _response;
}
}
I hope this points you in he right direction!
How about iterating over your Headers and adding them to the Content object:
var content = new StringContent(requestString, Encoding.UTF8);
// Iterate over current headers, as you can't set `Headers` property, only `.Add()` to the object.
foreach (var header in httpHeaders) {
content.Headers.Add(header.Key, header.Value.ToString());
}
response = client.PostAsync(Url, content).Result;
Now, they're sent in one method.
If you are still looking into this you can also add headers at the request level as well as the HttpClient level. This works for me:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
I am using REST call, the code is like:
public bool restfunc(string id)
{
var result = Task.Factory.StartNew(() => RunAsync(id)).Result; //RunAsync(id).Wait();
return true;
}
public static Task RunAsync(string id)
{
try
{
dynamic result = null;
string pathValue = WebConfigurationManager.AppSettings["R2G2APIUrl"];
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(pathValue);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.Timeout = TimeSpan.FromMinutes(5);
Task responsetask = null;
var jobid = id.Split('_')[1];
client.GetAsync("OnTranscriptionStarted/" + jobid).ContinueWith((requesttask) =>
{
responsetask = requesttask;
HttpResponseMessage resp = requesttask.Result; //HERE ERR OCCUR
resp.EnsureSuccessStatusCode();
resp.Content.ReadAsStringAsync().ContinueWith((readtask) =>
{
result = JsonConvert.DeserializeObject(readtask.Result);
});
});
}
return result;
Doubt:
I have API in pathvalue..I have to write pathvalue in
GetAsync() or function name and id which I want to call?
Help me out from this problem please..
You can use UriBuilder for that:
var builder = new UriBuilder(
"http", pathValue, 80, string.Format("OnTranscriptionStarted/{0}", jobId));
client.GetAsync(builder.Uri.ToString());
Given that I have the following web api method in my controller
public HttpResponseMessage PostGrantAccess(GrantAccessRequest grantAccessRequest)
{
var deviceId = grantAccessRequest.DeviceId;
var grantAccessResponse = new GrantAccessResponse()
{
Status = "OK"
};
var response = Request.CreateResponse<GrantAccessResponse>(HttpStatusCode.OK, grantAccessResponse);
return response;
}
Client calling code:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:55208/");
var request = new GrantAccessRequest { DeviceId = "bla" };
var response = client.PostAsJsonAsync("api/accesspanel", request).Result;
if (response.IsSuccessStatusCode)
{
var uri = response.Headers.Location;
}
}
How do I get back GrantAccessResponse at the client?
response.Content.ReadAsAsync<GrantAccessResponse>()