//request init
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(client.BaseAddress + ""),
Content = jsonContent
};
Console.WriteLine(request.Method);
var response = await client.SendAsync(request);
Console.WriteLine(response.RequestMessage);
The Request message shows that it was sent as GET, even though I set Method to Post
I think your endpoint is doing a redirect, try turning that off via the HttpClientHandler.
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var client = new HttpClient(handler);
// Do your work.
your code is doing the right thing. here's a console app that does the same thing, and the outcome is the right one. an Https POST call is done to the configured URL.
using System;
using System.Net.Http;
namespace testapicall
{
class Program
{
static void Main(string[] args)
{
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://google.com")
};
Console.WriteLine(request.Method);
var response = client.SendAsync(request).GetAwaiter().GetResult();
Console.WriteLine(response.RequestMessage);
}
}
}
and here's the console log output: Method: POST, RequestUri: https://google.com/', Version: 1.1, Content: , Headers:{}
what is the resource behind the URL you're trying to call doing? Maybe it is redirecting to another resource, by doing a GET request.
I recommend to use the RestClient to execute the Rest APIs.
Please refer the following URL and sample code
https://restsharp.dev/
var client = new RestClient("URL");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("accept", "application/json");
request.AddParameter("parameter name", "values");
IRestResponse response = client.Execute(request);
var data = (JObject)JsonConvert.DeserializeObject(response.Content);
Related
Imagine you are making a HTTP request for example (though it could be any http call):
string baseurl = LocalConfigKey.BaseUrl;
string geturl = string.Format("{0}leo-platform-api/api/v1/Orchestrator/Endpoint", baseurl);
var response = string.Empty;
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Ocp-Apim-Subscription-Key", LocalConfigKey.APIMSubscriptionKey);
HttpResponseMessage result = httpClient.GetAsync(geturl).GetAwaiter().GetResult();
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
response = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}
}
Is it possible to generate curl out of this request that can be logged in a db etc ?
You can use this package to convert HTTPClient to curl:
First install NuGet package:
dotnet add package HttpClientToCurl
Example:
Declare request requirements:
string requestBody = #"{ ""name"" : ""amin"",""requestId"" : ""10001000"",""amount"":10000 }";
string requestUri = "api/test";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
httpRequestMessage.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
using var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://localhost:1213");
Get curl from request
httpClient.GenerateCurlInConsole(httpRequestMessage, requestUri ); // Generate curl in console
httpClient.GenerateCurlInFile(httpRequestMessage, requestUri ); // Generate curl in file
HTTP call
// Call PostAsync => await client.PostAsync(requestUri, httpRequest.Content);
To get more information see the repo GitHub docs
I have deployed a python machine learning code using fastapi but sometimes it is giving me the response and sometimes it doesn't. How to force it to wait for API response every time . Please help me I'm having hard time with this.
var client = new RestClient("http://127.0.0.1:8000/predictbuy");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var param = new GannJson1{
Diff_Step=V1_SStep,
Last_Swing_Bars=V2_SSwing,
H1= V3_SH1,
L1=V4_SL1,
O1=V5_SO1,
C1=V6_SC1,
V1=V7_SV1,
HiLo1=V8_SHiLo1,
H2=V9_SH2,
L2=V10_SL2,
O2=V11_SO2,
C2=V12_SC2,
V2=V13_SV2,
HiLo2=V14_SHiLo2,
H3=V15_SH3,
L3=V16_SL3,
O3=V17_SO3,
C3=V18_SC3,
V3=V19_SV3,
HiLo3=V20_SHiLo3
};
request.AddJsonBody(param);
var response1 = client.Execute(request);
char pred1=(response1.Content)[1];
Please check this fucntion :
public async void Function()
{
var client = new RestClient();
var request = new RestRequest("http://www.google.com");
var cancellationTokenSource = new CancellationTokenSource();
var restResponse = await client.ExecuteAsync(request, cancellationTokenSource.Token);
var result = restResponse.Content;
}
I'm trying to implement a rest client in c# .net core that needs to first do Basic Authentication, then leverage a Bearer token in subsequent requests.
When I try to do Basic Authentication in combination with client.PostAsync with a FormUrlEncodedContent object, I'm getting an exception:
System.InvalidOperationException occurred in System.Net.Http.dll: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
//setup reusable http client
HttpClient client = new HttpClient();
Uri baseUri = new Uri(url);
client.BaseAddress = baseUri;
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.ConnectionClose = true;
//Post body content
var values = new List<KeyValuePair<string,string>>();
values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
var content = new FormUrlEncodedContent(values);
//Basic Authentication
var authenticationString = $"{clientId}:{clientSecret}";
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString));
content.Headers.Add("Authorization", $"Basic {base64EncodedAuthenticationString}");
//make the request
var task = client.PostAsync("/oauth2/token",content);
var response = task.Result;
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBody);
Exception has occurred: CLR/System.InvalidOperationException
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Net.Http.dll: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'
at System.Net.Http.Headers.HttpHeaders.GetHeaderDescriptor(String name)
at System.Net.Http.Headers.HttpHeaders.Add(String name, String value)
It looks like you can't use PostAsync and have access to mess with the Headers for authentication. I had to use an HttpRequestMessage and SendAsync.
//setup reusable http client
HttpClient client = new HttpClient();
Uri baseUri = new Uri(url);
client.BaseAddress = baseUri;
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.ConnectionClose = true;
//Post body content
var values = new List<KeyValuePair<string, string>>();
values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
var content = new FormUrlEncodedContent(values);
var authenticationString = $"{clientId}:{clientSecret}";
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString));
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/oauth2/token");
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);
requestMessage.Content = content;
//make the request
var task = client.SendAsync(requestMessage);
var response = task.Result;
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBody);
It's not a good practice to create HttpClients explicitly from your calling code.
Please use HttpClientFactory that simplifies a lot of things.
However, if you want to use basic authentication, just create an HttpRequestMessage and add the following header:
var request = new HttpRequestMessage(HttpMethod.Post, getPath)
{
Content = new FormUrlEncodedContent(values)
};
request.Headers.Authorization = new BasicAuthenticationHeaderValue("username", "password");
// other settings
If you decide to use a recommended IHttpClientFactory it's even simpler:
serviceCollection.AddHttpClient(c =>
{
c.BaseAddress = new Uri("your base url");
c.SetBasicAuthentication("username", "password");
})
Don't encode the whole authentication string - encode the "Username:Password" expression and append the result to the "Basic " prefix.
var authenticationString = $"{clientId}:{clientSecret}";
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.UTF8.GetBytes(authenticationString));
content.Headers.Add("Authorization", "Basic " + base64EncodedAuthenticationString);
Also, consider using just ASCII encoding - the UTF8 may not be understood by the server unless you add a charset declaration to the header.
Wikipedia seems to cover this quite well.
The specific problem is this line (below)
content.Headers.Add("Authorization", $"Basic {base64EncodedAuthenticationString}");
This fails because HttpContent.Headers (System.Net.Http.Headers.HttpContentHeaders) is only for headers that are content-specific, such as Content-Type, Content-Length, and so on.
You've stated that you can't use DefaultRequestHeaders because you only need it for a single request - but you also can't use it with PostAsync - only SendAsync provided you construct the HttpRequestMessage yourself, as per your own answer and #NeilMoss' answer - but you could use an extension-method in future.
But for the benefit of other readers, another alternative is to add a new extension method based on the existing PostAsync, which is actually really simple (only 3 lines!):
public Task<HttpResponseMessage> PostAsync( this HttpClient httpClient, Uri requestUri, HttpContent content, String basicUserName, String basicPassword, String? challengeCharSet = null, CancellationToken cancellationToken = default )
{
if( basicUserName.IndexOf(':') > -1 ) throw new ArgumentException( message: "RFC 7617 states that usernames cannot contain colons.", paramName: nameof(basicUserName) );
HttpRequestMessage httpRequestMessage = new HttpRequestMessage( HttpMethod.Post, requestUri );
httpRequestMessage.Content = content;
//
Encoding encoding = Encoding.ASCII;
if( challengeCharSet != null )
{
try
{
encoding = Encoding.GetEncoding( challengeCharSet );
}
catch
{
encoding = Encoding.ASCII;
}
}
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(
scheme : "Basic",
parameter: Convert.ToBase64String( encoding.GetBytes( userName + ":" + password ) )
);
return SendAsync( httpRequestMessage, cancellationToken );
}
Usage:
HttpClient httpClient = ...
using( HttpResponseMessage response = await httpClient.PostAsync( uri, content, basicUserName: "AzureDiamond", basicPassword: "hunter2" ).ConfigureAwait(false) )
{
// ...
}
Just something to add that I struggled with, which I only experienced with Basic authentication endpoints. If you add Json as StringContent then it adds a charset=utf-8, this often return a BadRequest 400.
Here is the code I got to fix this: reference:
https://dzone.com/articles/httpclient-how-to-remove-charset-from-content-type
using (var client = new HttpClient())
using (var content = new StringContent(ParseJSON(data), Encoding.Default, "application/json"))
{
//Remove UTF-8 Charset causing BadRequest 400
content.Headers.ContentType.CharSet = "";
var clientId = "client";
var clientSecret = "secret";
var authenticationString = $"{clientId}:{clientSecret}";
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.UTF8.GetBytes(authenticationString));
client.DefaultRequestHeaders.TryAddWithoutValidation(authHeader, authorization);
var response = await client.PostAsync(url, content);
return response;
}
I have resolve this by using below code, that serve my purpose also. Added Code for both Get/Post, this will help you. Moreover I have added one more Header key. So to pass extra data to header. Hope that will resolve your issue.
class Program {
private static readonly string Username = "test";
private static readonly string Password = "test#123";
static void Main(string[] args) {
var response = Login();
}
public static async Task Login()
{
var anotherKey ="test";
HttpClient httpClient = new HttpClient
{
BaseAddress = new Uri("https://google.com/")
};
httpClient.DefaultRequestHeaders.Add($"Authorization", $"Basic {Base64Encode($"{Username}:{Password}")}");
httpClient.DefaultRequestHeaders.Add($"anotherKey", $"{anotherKey}");
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync("user/123").ConfigureAwait(false);
// For Get Method
var response= await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
// For Post Method
User user = new User (1,"ABC");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsJsonAsync("/post", user).ConfigureAwait(false);
UserDetail userDetail = await httpResponseMessage.Content.ReadAsAsync<UserDetail>().ConfigureAwait(false);
}
}
Using .NET 6, I use the HttpClient.DefaultRequestHeaders.Authorization property to set the Authorization header.
// This example will send a signing request to the RightSignature API
var api = "https://api.rightsignature.com/public/v2/sending_requests";
// requestJson is the serialized JSON request body
var contentData = new StringContent(requestJson, Encoding.UTF8, "application/json");
// Instantiate client (for testing), use Microsoft's guidelines in production
var client = new HttpClient();
// Use basic auth, the token has already been converted to base64
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", tokenB64);
try
{
var response = await client.PostAsync(api, contentData);
}
...
Good luck!
I am trying to use HttpClient to post a NameValueCollection to a specific Url. I have the code working using WebClient, but I'm trying to figure out if it is possible to do using HttpClient.
Below, you will find my working code that uses WebClient:
var payloadJson = JsonConvert.SerializeObject(new { channel, username, text });
using (var client = new WebClient())
{
var data = new NameValueCollection();
data["payload"] = payloadJson;
var response = client.UploadValues(_uri, "POST", data);
var responseText = _encoding.GetString(response);
}
I'm using this code to try to post a message to a Slack Channel using a web integration. Is there a way to implement this same functionality while using HttpClient?
The Slack error that I receive when I try to use HttpClient is "missing_text_or_fallback_or_attachment".
Thanks in advance for any help!
Using HttpClient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://yourdomain.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new NameValueCollection();
data["payload"] = payloadJson;
StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync("api/yourcontroller", content);
if (response.IsSuccessStatusCode)
{
//MessageBox.Show("Upload Successful", "Success", MessageBoxButtons.OK);
}
}
catch (Exception)
{
// ignored
}
}
While you are tagging #slack in the question, I suggest you to use Slack.Webhooks nuget package.
Example usage I found is in here;
https://volkanpaksoy.com/archive/2017/04/11/Integrating-c-applications-with-slack/
var url = "{Webhook URL created in Step 2}";
var slackClient = new SlackClient(url);
var slackMessage = new SlackMessage
{
Channel = "#general",
Text = "New message coming in!",
IconEmoji = Emoji.CreditCard,
Username = "any-name-would-do"
};
slackClient.Post(slackMessage);
I am a newbie to Mailgun and REST and need some help.
If I use the Mailgun provided code:
RestClient client = new RestClient();
client.BaseUrl = "https://api.mailgun.net/v2";
client.Authenticator = new HttpBasicAuthenticator("api", "xxxx");
RestRequest request = new RestRequest();
request.Resource = "/address/validate";
request.AddParameter("address", "me#mydomain.com");
return client.Execute(request);
How do I retrieve and process the response that the address is valid or not?
This code works for me. I didn't use RESTClient and wrote my own code(which works perfectly fine)
[System.Web.Services.WebMethod]
public static object GetEmailInfo(string UserName)
{
var http = (HttpWebRequest)WebRequest.Create("https://api.mailgun.net/v2/address/validate?address=" + UserName);
http.Credentials = new NetworkCredential("api","public key");
http.Timeout = 5000;
try
{
var response = http.GetResponse();
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();
JSON.JsonObject js = new JSON.JsonObject(content);
return Convert.ToBoolean(js["is_valid"]);
}
catch (Exception ex)
{
}
}
First of You should never post private information such as your public key of such API
Just by using the amazing Postman Chrome app you can see the result of such request:
click here to see the image below in full resolution
and I'm sure, if you instead of return client.Execute(request); you do
var result = client.Execute(request);
return result;
and adding a breakpoint in the return you can inspect what is the object that is passed from the call... without testing, I'm sure you can convert result.Content (as it's where RestSharp appends the response content) into an object and use that object (or use the dynamic type).
now, testing your code in VS:
click here to see the image below in full resolution
you can then use the dynamic object like:
click here to see the image below in full resolution
public void GetResponse()
{
var client = new RestClient();
client.BaseUrl = "https://api.mailgun.net/v2";
client.Authenticator = new HttpBasicAuthenticator("api", "pubkey-e82c8201c292691ad889ace3434df6cb");
var request = new RestRequest();
request.Resource = "/address/validate";
request.AddParameter("address", "me#mydomain.com");
var response = client.Execute(request);
dynamic content = Json.Decode(response.Content);
bool isValid = content.is_valid;
string domain = content.parts.domain;
}
and treat the content of the response just like the json passed:
{
"address": "me#mydomain.com",
"did_you_mean": null,
"is_valid": true,
"parts": {
"display_name": null,
"domain": "mydomain.com",
"local_part": "me"
}
}