I'm having trouble making POST using http client with Accept, ContentType and Authentication as headers. I tried several implementations using send aysnc and post async and all seemed to fail. I used https://www.hurl.it/ to make sure if it also was getting a time out error but it is working, getting back json data.
I get a connection time out error exception (in: var response = await client.SendAsync(request);) when running the below code.
Also I have curl command which i was trying to go off by, which is listed below as well.
Implementation:
// Body
var dictionary = new Dictionary<string, string>();
dictionary.Add("id", "123");
var formData = new List<KeyValuePair<string, string>>();
formData.Add(new KeyValuePair<string, string>("id", "123"));
// Http Client
var client = new HttpClient();
client.BaseAddress = new Uri("https://www.some_website.com/api/house");
// Http Request
var request = new HttpRequestMessage(HttpMethod.Post, "https://www.some_website.com/api/house");
// Accept
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Content-Type
//request.Content = new FormUrlEncodedContent(dictionary);
var httpContent = new StringContent(
JsonConvert.SerializeObject(
dictionary,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
}),
Encoding.UTF8,
"application/json");
request.Content = new StringContent(
JsonConvert.SerializeObject(
dictionary,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
}),
Encoding.UTF8,
"application/json");
// Authentication
var byteArray = new UTF8Encoding().GetBytes("user" + ":" + "pass");
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
// Communication
try
{
var response = await client.SendAsync(request);//PostAsync("https://www.some_website.com/api/house", httpContent);
if (response.IsSuccessStatusCode)
{
var myContent = await response.Content.ReadAsStringAsync();
var deliveryStatus = JsonConvert.DeserializeObject<MyOjbect>(myContent);
}
}
catch (Exception e)
{
//catch error
}
Curl:
curl -i --user user:123 -H Accept:application/json -H content-type:application/json -H cache-control:no-cache -X POST https://www.some_website.com/api/house -H Content-Type: application/json -d '{"id": "123"}'
You set your BaseAddress and the HttpRequestMessage Uri property both to the same absolute url, shouldn't it be the base address (ex. somewebsite.com) and the relative url (ex. (api/house). You can also inspect your request with Fiddler telerik.com/fiddler
Related
I am able to make the following request in Postman but not able to in C#. I'm guessing it's due to the json but tried a few different ways and still nothing.
Postman:
curl --location --request POST 'https://login.sandbox.payoneer.com/api/v2/oauth2/token' \
--header 'Authorization: Basic *ENCRYPTEDPASSCODE FROM ClientID & Secret*' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=read write'
My Code returns text "ErrorParams":null:
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.sandbox.payoneer.com/api/v2/oauth2/token");
var authString = $"{clientID}:{secret}";
var encodedString = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(authString));
request.Headers.Add("Authorization", $"Basic {encodedString}");
string json = JsonConvert.SerializeObject(new
{
grant_type = "client_credentials",
scope = "read write"
});
request.Content = new StringContent(json, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await client.SendAsync(request).ConfigureAwait(false);
var responseText = await response.Content.ReadAsStringAsync();
return responseText;
If you need to set the content as application/x-www-form-urlencoded then use FormUrlEncodedContent
var dict = new Dictionary<string, string>();
dict.Add("grant_type", "client_credentials");
dict.Add("scope", "read write");
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.sandbox.payoneer.com/api/v2/oauth2/token") { Content = new FormUrlEncodedContent(dict) };
var response = await client.SendAsync(request).ConfigureAwait(false);
var responseText = await response.Content.ReadAsStringAsync();
If you are serializing the request body to JSON, then you need to set the Content-Type as application/json
request.Headers.Add("Content-Type", "application/json");
There is a code like this:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.TryAddWithoutValidation("User-Agent", userAgent);
request.Content = new StringContent("{" +
$"\"grant_type\":\"authorization_code\"," +
$"\"client_id\":\"*****\"," +
$"\"client_secret\":\"****\"," +
$"\"code\":\"{autorizationCode}\"," +
$"\"redirect_uri\":\"urn:ietf:wg:oauth:2.0:oob\"" +
"}", Encoding.UTF8);
var response = await client.SendAsync(request);
Token = response.Content.ReadAsStringAsync().Result.ToString();
}
When I send a request, it gives me an error - "{"error":"invalid_request","error_description":"Missing required parameter: grant_type."}", but grant_type is present.
The request on the site looks like this:
curl -X POST "https://site/oauth/token" \
-H "User-Agent: APPLICATION_NAME" \
-F grant_type="authorization_code" \
-F client_id="CLIENT_ID" \
-F client_secret="CLIENT_SECRET" \
-F code="AUTORIZATION_CODE" \
-F redirect_uri="REDIRECT_URI"
Why is he giving this error? How can I fix it?
The CURL-Parameter -F represents form content, not JSON-Content.
If you want to send FormContent, you cannot use StringContent, you need to use FormUrlEncodedContent, like this:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.TryAddWithoutValidation("User-Agent", userAgent);
request.Content = new FormUrlEncodedContent( new List<KeyValuePair<string, string>>() {
new KeyValuePair<string,string>("grant_type", "authorization_code"),
new KeyValuePair<string,string>("client_id", "*****"),
new KeyValuePair<string,string>("client_secret", "*****"),
new KeyValuePair<string,string>("code", $"{autorizationCode}"),
new KeyValuePair<string,string>("redirect_uri", "urn:ietf:wg:oauth:2.0:oob")
} );
var response = await client.SendAsync(request);
Token = response.Content.ReadAsStringAsync().Result.ToString();
}
/Edit: Regarding your comment, your endpoint also supports JSON and you missed the content-type. I'll leave this here in case anyone gets into the problem with an exact CURL-Request like you mentioned.
I am having issues constructing the POST request with form-data in C# using HTTPClient. i tried multiple approaches but nothing seems to work. Can you please help what I am missing?
Please be informed, the SWAGGER POST is working fine and based on that I am trying to construct the request.
The API parameters
rPath* string
(formData)
nName* string
(formData)
nFile string
(formData)
type* string
(formData)
zFile file
file
The working swagger POST
curl -X POST "http://localhost:8888/server/api/v1.0/createfolder" -H "accept: text/plain; charset=UTF-8" -H "authorization: Basic XXXXXXX" -H "Content-Type: multipart/form-data" -F "rPath=/RootFolder/" -F "nName=testing" -F "type=Folder"
The Fiddler request header of the SWAGGER POST (This is working).
static void Main(string[] args)
{
var formData = new MultipartFormDataContent();
HttpContent content = new FormUrlEncodedContent (new[]
{
new KeyValuePair<string, string>("rPath", "/RootFolder/"),
new KeyValuePair<string, string>("nName", "TestFolder"),
new KeyValuePair<string, string>("type", "Folder")
});
content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
formData.Add(content);
var url = "http://localhost:8888/server/api/v1.0/createfolder";
HttpResponseMessage response = PostRoot(formData, url);
}
static HttpResponseMessage PostRoot(HttpContent content, string webMethod)
{
HttpResponseMessage response = new HttpResponseMessage();
using (var client = new HttpClient() { })
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "xxxxxxx=");
response = client.PostAsync(webMethod, content).Result;
}
return response;
}
Here's an example of how to send multi part form data:
var client = new HttpClient();
var baseUrl = "https://someurl";
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "multipart/form-data");
var formContent = new MultipartFormDataContent
{
{new StringContent("ParamValue1"),"ParamName1"},
{new StringContent("ParamValue2"),"ParamName2"},
{new StringContent("ParamValue2"),"ParamName3"},
};
var response = client.PostAsync(baseUrl, formContent).Result;
response.EnsureSuccessStatusCode();
var result = string.Empty;
if (response.IsSuccessStatusCode)
{
result = response.Content.ReadAsStringAsync().Result;
}
return result;
I am using the Forge API.
I need to execute PATCH request.
When I send it using Postman everything is fine, but when I build request using HttpRequestMessage I get a response - "415 unsupported media type".
By API documentation Content-Type I set to "application/vnd.api+json".
Body of request in Postman
Headers of request in Postman
request object structure
JObject jsonApi = new JObject();
jsonApi.Add("version", "1.0");
JObject attributes = new JObject();
attributes.Add("displayName", file.FileName);
JObject data = new JObject();
data.Add("type", "items");
data.Add("id", file.ExternalFileId);
data.Add("attributes", attributes);
JObject request = new JObject();
request.Add("jsonapi", jsonApi);
request.Add("data", data);
using (var httpClient = new HttpClient())
{
HttpRequestMessage http = new HttpRequestMessage
{
RequestUri = new Uri(url),
Method = new HttpMethod("PATCH"),
Headers =
{
{ HttpRequestHeader.Authorization.ToString(), "Bearer " + userLastAccessToken },
{ HttpRequestHeader.Accept.ToString(), "application/vnd.api+json" }
}
};
http.Content = new StringContent(request.ToString(), Encoding.UTF8, "application/vnd.api+json");
HttpResponseMessage responseMessage = await httpClient.SendAsync(http);
}
Try again with "application/json" or use HttpHeaders.TryAddWithoutValidation ("application/vnd.api+json" might not sit well with the internal validation of HttpHeaders):
http.Content = new StringContent(request.ToString(), Encoding.UTF8, "application/json");
Or:
http.Content = new StringContent(request.ToString(), Encoding.UTF8);
http.Headers.TryAddWithoutValidation("Content-Type", "application/vnd.api+json");
Ok, I solved the problem by setting ContentType in this way
http.Content = new StringContent(request.ToString(), Encoding.UTF8);
http.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/vnd.api+json");
I'm trying to set the content-type of my HttpClient Post request, and use the profile parameter, but when I change the content type I get an exception thrown:
"The format of value 'application/json; profile={URL HERE}' is
invalid."
For reference, I found this Q&A: Zoopla Sandbox with cURL http header error
X509Certificate2 cert = new X509Certificate2("cert.pfx", "PASSWORD");
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://realtime-listings-api.webservices.zpg.co.uk");
var stringContent = new StringContent(propertyData, Encoding.UTF8, "application/json; profile=http://realtime-listings.webservices.zpg.co.uk/docs/v1.1/schemas/listing/list.json");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var response = await client.PostAsync("/sandbox/v1/listing/list", stringContent);
return _resultFactory.Create(true, await response.Content.ReadAsStringAsync());
If you create a HttpRequestMessage and use client.SendAsync(), you can add the parameters to request.Content.Headers.ContentType.Parameters
var client = new HttpClient();
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://realtime-listings-api.webservices.zpg.co.uk/sandbox/v1/listing/list"))
{
request.Content = new StringContent("propertyData", Encoding.UTF8, "application/json");
request.Content.Headers.ContentType.Parameters.Add(
new NameValueHeaderValue("profile", "http://realtime-listings.webservices.zpg.co.uk/docs/v1.1/schemas/listing/list.json")
);
var response = await client.SendAsync(request);
//Handle response..
}
You don't need to use HttpRequestMessage but you do need to add the profile value as a quoted string via the NameValueHeaderValue parameter:
var content = new StringContent(request.ToJson(), Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("profile", "\"https://realtime-listings.webservices.zpg.co.uk/docs/v1.2/schemas/listing/update.json\""))
httpClient.PostAsync("listing/update", content);
This will get round the FormatException. Otherwise you will run into this dotnet bug.