Is the StringContent the same as params (form data)? - c#

I'm using the following code to post a message to the server.
String credentials="email=me#here.com&pass=abc123";
using (HttpClient client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(
url, new StringContent(credentials));
result = await message.Content.ReadAsStringAsync();
}
However, the server responds with an error message saying that the email or pass isn't there.
{\"status\":\"error\",\"message\":\"Email or pass is missing\"}
Now, I can see it's lying but what can be done about it? Am I not providing the credentials as post data (the equivalent of "params" that can be seen if invoked from URL line in FF, as the image below shows?
I also noticed that when I access the RequestMessage like below, I get the URL but no credentials having been sent. What stupid thing am I missing?!
result = message.RequestMessage.ToString();
This result gives me the following string.
Method: POST, RequestUri: 'https://server.com/gettoken', Version: 1.1, Content: System.Net.Http.StringContent, Headers:\u000d\u000a{\u000d\u000a Content-Type: text/plain; charset=utf-8\u000d\u000a Content-Length: 56\u000d\u000a}

You should use the FormUrlEncodedContent to pass your POST data, instead of a StringContent object.
var credentials = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("email", "me#here.com"),
new KeyValuePair<string, string>("pass", "abc123")
});
using (HttpClient client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(
url, credentials);
result = await message.Content.ReadAsStringAsync();
}

Related

Set request header for POST method using Content-Type, Authorization-User and Authorization-Key in HTTPClient C#

I spent a lot of time looking for an answer, but I didn't find it. I need to send a POST to an API using HTTPClient in C# in the following format:
POST endpoint URL
Content-Type: application/json
Authorization-User: email address
Authorization-Key: EMP-generated key
{
request body
}
Authorization-User and Authorization-Key are required in headers and cannot be replaced by username and password name.
When I use my code described below I got the exception in line client.DefaultRequestHeaders.Add: "Incorrect header name. Check if request headers are used with HttpRequestMessage, response headers with HttpResponseMessage and content headers with HttpContent objects".
Can someone help me?
My code:
var client = new HttpClient();fdaJsonCons ofdaJson = new fdaJsonCons();
fdaFilters oFdaFilter = new fdaFilters();
ofdaJson.filters = oFdaFilter;
string stJson = JsonConvert.SerializeObject(ofdaJson);
string vContentType = "application/json";
var content = new StringContent(JsonConvert.SerializeObject(stJson), Encoding.Default, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(vContentType));
client.DefaultRequestHeaders.Add("Content-Type", String.Format("Basic {0}", "application/json"));
client.DefaultRequestHeaders.Add("Authorization", String.Format("Authorization-User {0}", "my-email"));
client.DefaultRequestHeaders.Add("Authorization", String.Format("Authorization-Key {0}", "my-keyvalue"));
var result = await client.PostAsync(url, content);
var result_string = await result.Content.ReadAsStringAsync();

Presigned PUT works from PostMan, but 403 Forbidden from C# HttpClient

I have generated a pre-signed url from S3 using the following .Net code (in a service that has the appropriate IAM role/permission for the bucket)
var key = GenerateKey(jobId, batchId);
var linkExpiresAt = _dateTimeService.Now().AddMinutes(_expiryTime);
var request = new GetPreSignedUrlRequest
{
BucketName = _bucketName,
Key = key,
Verb = HttpVerb.PUT,
ContentType = "application/json",
Expires = linkExpiresAt,
ServerSideEncryptionMethod = ServerSideEncryptionMethod.None
};
var url = _s3Client.GetPreSignedURL(request);
I can use this url in Postman to do a PUT with content 'JSON', but when I try to use it from code, I get 403
var content = new StringContent(mooStr, Encoding.ASCII, "application/json");
var fileStreamResponse = await httpClient.PutAsync(
url,
content);
Is there anything that stands out as wrong with the .Net attempt to PUT to the url?
If anyone comes across the same issue, I found the solution.
When I ran Fiddler, I captured the successful request from Postman and the failing request from .Net code. The only difference I could spot was that the successful one had this header (I'd changed to text/plain since my first post, but the problem remained):-
Content-Type: text/plain
and the failing one from .Net had:-
Content-Type: text/plain; charset=utf-8
A bit of a search around StackOverflow found me these posts
How to remove charset=utf8 from Content-Type header generated by HttpClient.PostAsJsonAsync()?
How do I not exclude charset in Content-Type when using HttpClient?
I edited the captured request in Fiddler and removed the charset and it worked. Altering my original code to the following worked (note - setting text/plain on the StringContent didn't work):-
var content = new StringContent(mooStr);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/plain");
var fileStreamResponse = await httpClient.PutAsync(
Url,
content);
Following code worked for me (for posting a file of type IFormFile):
public async Task<bool> UploadObject(string preSignedUrl)
{
try
{
using (var client = new HttpClient())
{
StreamContent streamContent = new StreamContent(file.OpenReadStream());
var result = await client.PutAsync(preSignedUrl, streamContent);
if (result.StatusCode != HttpStatusCode.OK)
{
throw new Exception();
}
}
return true;
}
catch (Exception e)
{
....
}
return false;
}
Create the preSignedUrl with the IAmazonS3 package.

Xamarin Forms Post Request Body

public async static Task<RootUserData> getUSerLoggedIn(string userName, string password)
{
RootUserData rootUserData = new RootUserData();
var url = URlConstants.LOGIN_URL;
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes($"{userName}:{password}");
httpClient.DefaultRequestHeaders.Add("content-type", "application/json");
httpClient.DefaultRequestHeaders.Add("cache-control", "no-cache");
} ;
}
I am using above code to make one Service call. I have to pass userEmailAddress in body as plain as shown in Postman Picture. Can You Please help me How to achieve this?
No... Its in Plain Text
Set your content mime type to "text/plain":
httpClient.DefaultRequestHeaders.Add("content-type", "text/plain");
And post a string:
var response = await httpClient.PostAsync(url, new StringContent(userName));
Content-Type should not be added like that, It didn't work in my case, and gave a wrong response, instead
Pass content-Type like this -
httpRequest.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");

REST JSON GET - 400 Bad Request

I am working with the Basecamp API which is a REST (JSON) API using basic HTTP authentication over HTTPS.
This should be a GET request but when I run my code using GET I am receiving:
Cannot send a content-body with this verb-type
When I run it as a POST, I receive:
{"status":"400","error":"Bad Request"}
Does anyone know why this may be occurring?
using (var httpClient = new HttpClient()) {
string userName = "someone#someone.com";
string password = "somepassword";
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", userName, password)));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, "https://correctUrlHere);
requestMessage.Headers.Add("User-Agent", "TheProject (someone#someone.com)");
requestMessage.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(requestMessage);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
In this code I obviously swapped out the username, password, project name, and URL but in the actual code they are all correct.
GET requests must pass their parameters as url query and not as request body.
http://example.com?p1=1&p2=helloworld
If you don't have any content, as your example suggests, omit setting it on the request.
The BadRequest result indicates some error with your payload (again: content seems to be empty).

Set request Content-Type on WinRT HttpClient

I'm developing a Windows 8.1 Store apps with C# and .NET Framework 4.5.1.
I'm trying to do a POST to a REST API but I get an Unsupported Media Type with this code:
public async Task<HttpResponseMessage> POST(string url, string jsonContent)
{
Uri resourceUri;
resourceUri = ValidateUri(url);
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
HttpRequestHeaderCollection headers = httpClient.DefaultRequestHeaders;
// Try to add user agent to headers.
if (headers.UserAgent.TryParseAdd(_userAgent))
headers.UserAgent.ParseAdd(_userAgent);
// Add Content-Type and Content-Length headers
headers.Accept.Add(new HttpMediaTypeWithQualityHeaderValue("application/json"));
response = await httpClient.PostAsync(resourceUri, new HttpStringContent(jsonContent));
return response;
}
If I change this line:
response = await httpClient.PostAsync(resourceUri, new HttpStringContent(jsonContent));
With this one:
response = await httpClient.PostAsync(resourceUri, new HttpStringContent(string.Empty));
It works. I don't get 415 status code.
jsonContent value is:
{"UserName":"My Name","Provider":"Facebook","ExternalAccessToken":"Access token omitted"}
Because I haven't found any similar code on Internet, and I only have 4 views on this question; I will share the answer.
I have fixed this problem changing the post with this code:
response = await httpClient.PostAsync(resourceUri,
new HttpStringContent(jsonContent, UnicodeEncoding.Utf8, "application/json"));
You can pass "Content-Type" on HttpStringContent constructor. More info here.

Categories

Resources