How can I add a HTTP Header called "Content-Type" to an HttpClient request? [duplicate] - c#

I need to add http headers to the HttpClient before I send a request to a web service. How do I do that for an individual request (as opposed to on the HttpClient to all future requests)? I'm not sure if this is even possible.
var client = new HttpClient();
var task =
client.GetAsync("http://www.someURI.com")
.ContinueWith((taskwithmsg) =>
{
var response = taskwithmsg.Result;
var jsonTask = response.Content.ReadAsAsync<JsonObject>();
jsonTask.Wait();
var jsonObject = jsonTask.Result;
});
task.Wait();

Create a HttpRequestMessage, set the Method to GET, set your headers and then use SendAsync instead of GetAsync.
var client = new HttpClient();
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://www.someURI.com"),
Method = HttpMethod.Get,
};
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
var task = client.SendAsync(request)
.ContinueWith((taskwithmsg) =>
{
var response = taskwithmsg.Result;
var jsonTask = response.Content.ReadAsAsync<JsonObject>();
jsonTask.Wait();
var jsonObject = jsonTask.Result;
});
task.Wait();

When it can be the same header for all requests or you dispose the client after each request you can use the DefaultRequestHeaders.Add option:
client.DefaultRequestHeaders.Add("apikey","xxxxxxxxx");

To set custom headers ON A REQUEST, build a request with the custom header before passing it to httpclient to send to http server.
eg:
HttpClient client = HttpClients.custom().build();
HttpUriRequest request = RequestBuilder.get()
.setUri(someURL)
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.build();
client.execute(request);
Default header is SET ON HTTPCLIENT to send on every request to the server.

Related

Send a string in body via SendRequestAsync

I need to send a Patch request to a backend API via SendRequestAsync func. This is regarding a UWP C# app.
Backend expected to like this:
On the app this is the code I wrote. But doesn't work
if (requestMehtod == ApplicationConstants.RequestType.PATCH)
{
Uri uri = new Uri(requestUrl);
HttpRequestMessage requestMessage = null;
if (postData != null)
{
var itemAsJson = JsonConvert.SerializeObject(postData);
requestMessage = new HttpRequestMessage(HttpMethod.Patch, uri)
{
Content = new HttpStringContent(itemAsJson, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json-patch+json")
};
}
else
{
requestMessage = new HttpRequestMessage(HttpMethod.Patch, uri);
}
response = await httpClient.SendRequestAsync(requestMessage).AsTask(cancellationTokenSource.Token);
var rdModel = ProcessResponseData(response);
return await Handle401Error(rdModel, response, postData, url, requestMehtod, isDownloadSite, OnSendRequestProgress, requestData);
}
The above code fine to send JSON data to the same API and works fine. But I need to know how to send just a string in the body. Thank for the consideration
NOTE: App uses HttpClient from Windows.Web.Http and will not be able to use anything inside System.Net.Http namespace.
The answer is given by the #gusman and #Simon Wilson. Just to amend to their answer, in order to be able to send a string in the request body, the string needs to be within double-quotes.
var requestData = "\"hello world\"";
var request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = new HttpStringContent(requestData, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json")
};
response = await httpClient.SendRequestAsync(request);
This worked in my scenario.

Is it possible to generate headers automatically with HttpClient / RestSharp?

At the moment I am using the following RestSharp request to get a website's content:
var client = new RestClient(productLink);
var request = new RestRequest(Method.GET);
request.AddHeader("Cookie", "insert-cookie-content");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
I have tried converting it into HttpClient as i will need to use the AllowRedirect property later:
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Cookie", "insert-cookie-content");
var response = await client.GetAsync(productUrl);
Console.WriteLine(response);
The URL I am trying to get a response from is: https://www.nike.com/sg/launch/t/air-max-90-orange-duck-camo
My first problem is that the HttpClient request is giving me 403 Errors whereas the RestClient request was working fine. How can I fix this?
My second problem is that the cookie expires after a couple of uses, and I have to manually get a new one from postman and insert it. Is there anyway for the request to generate its own cookie?
Here is the two fiddler responses compared: https://imgur.com/a/bZo7d9F
In case of HttpClient if you want to pass the Cookies manually through the DefaultRequestHeaders then you have to tell this to the HttpClient to do NOT use CookieContainer. You have to use HttpClientHandler's UseCookie flag to indicate it.
var client = new HttpClient(new HttpClientHandler { UseCookies = false });
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Cookie", "insert-cookie-content");
var response = await client.GetAsync(productUrl);
Console.WriteLine(response);

Getting Invalid Content Type doing a Delete httpclient call. What am I doing wrong?

When I try to do the code below, it just results in Invalid Content Type (with error number 612).
I'm trying to delete a lead id from a static list. I can add lead ids or get the static list leads fine.
The post and get calls I make are working fine, although the post calls I make seem to require the data right on the url string (as in $"{endpointURL}/rest/v1/lists/{listID}/leads.json?id={leadID}"; If I include the id as a json object, it fails too. This might be a clue to what I'm doing wrong with the delete call.
string url = $"{endpointURL}/rest/v1/lists/{listID}/leads.json?id={leadID}";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", _access_token);
HttpResponseMessage response = await client.DeleteAsync(url);
The response here always results in Invalid Content Type.
If I add this line before I do the deleteasync call, it gives me a different error before it even hits the deleteAsync call.
client.DefaultRequestHeaders.Add("Content-Type", "application/json");
Error is "Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."
Try using HttpRequestMessage in your code like this
string url = $"{endpointURL}/rest/";
HttpClient client = new HttpClient
{
BaseAddress = new Uri(url)
};
//I'm assuming you have leadID as an int parameter in the method signature
Dictionary<string, int> jsonValues = new Dictionary<string, int>();
jsonValues.Add("id", leadID);
//create an instance of an HttpRequestMessage() and pass in the api end route and HttpMethod
//along with the headers
HttpRequestMessage request = new HttpRequestMessage
(HttpMethod.Delete, $"v1/lists/{listID}") //<--I had to remove the leads.json part of the route... instead I'm going to take a leap of faith and hit this end point with the HttpMethod Delete and pass in a Id key value pair and encode it as application/json
{
Content = new StringContent(new JavaScriptSerializer().Serialize(jsonValues), Encoding.UTF8, "application/json")
};
request.Headers.Add("Bearer", _access_token);
//since we've already told the request what type of httpmethod we're using
//(in this case: HttpDelete)
//we could just use SendAsync and pass in the request as the argument
HttpResponseMessage response = await client.SendAsync(request);
The solution turned out to be a combination of a couple of suggestions.
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, data);
// The key part was the line below
request.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");
if (!string.IsNullOrEmpty(_access_token))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _access_token);
}
HttpResponseMessage response = await client.SendAsync(request);
This worked for me.

.NET HttpClient add query string and JSON body to POST

How do I set up a .NET HttpClient.SendAsync() request to contain query string parameters and a JSON body (in the case of a POST)?
// Query string parameters
var queryString = new Dictionary<string, string>()
{
{ "foo", "bar" }
};
// Create json for body
var content = new JObject(json);
// Create HttpClient
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.baseaddress.com/");
var request = new HttpRequestMessage(HttpMethod.Post, "something");
// Setup header(s)
request.Headers.Add("Accept", "application/json");
// Add body content
request.Content = new StringContent(
content.ToString(),
Encoding.UTF8,
"application/json"
);
// How do I add the queryString?
// Send the request
client.SendAsync(request);
Every example I've seen says to set the
request.Content = new FormUrlEncodedContent(queryString)
but then I lose my JSON body initialization in the request.Content
I ended up finding Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString() that was what I needed. This allowed me to add the query string parameters without having to build the string manually (and worry about escaping characters and such).
Note: I'm using ASP.NET Core, but the same method is also available through Microsoft.Owin.Infrastructure.WebUtilities.AddQueryString()
New code:
// Query string parameters
var queryString = new Dictionary<string, string>()
{
{ "foo", "bar" }
};
// Create json for body
var content = new JObject(json);
// Create HttpClient
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.baseaddress.com/");
// This is the missing piece
var requestUri = QueryHelpers.AddQueryString("something", queryString);
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
// Setup header(s)
request.Headers.Add("Accept", "application/json");
// Add body content
request.Content = new StringContent(
content.ToString(),
Encoding.UTF8,
"application/json"
);
// Send the request
client.SendAsync(request);
I can suggest that you use RestSharp for this purpose. It's basically a wrapper of the HttpWebRequest that does exactly what you want: makes it easy to compose url and body parameters and deserialize the result back.
Example from the site:
var client = new RestClient("http://example.com");
var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("id", "123"); // replaces matching token in request.Resource
// easily add HTTP Headers
request.AddHeader("header", "value");
// add files to upload (works with compatible verbs)
request.AddFile(path);
// execute the request
IRestResponse response = client.Execute(request);
This is simple and works for me:
responseMsg = await httpClient.PostAsJsonAsync(locationSearchUri, new { NameLike = "Johnson" });
The body of the requests look like { NameLike:"Johnson" }

Custom header to HttpClient request

How do I add a custom header to a HttpClient request? I am using PostAsJsonAsync method to post the JSON. The custom header that I would need to be added is
"X-Version: 1"
This is what I have done so far:
using (var client = new HttpClient()) {
client.BaseAddress = new Uri("https://api.clickatell.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "xxxxxxxxxxxxxxxxxxxx");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync("rest/message", svm).Result;
}
I have found the answer to my question.
client.DefaultRequestHeaders.Add("X-Version","1");
That should add a custom header to your request
Here is an answer based on that by Anubis (which is a better approach as it doesn't modify the headers for every request) but which is more equivalent to the code in the original question:
using Newtonsoft.Json;
...
var client = new HttpClient();
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.clickatell.com/rest/message"),
Headers = {
{ HttpRequestHeader.Authorization.ToString(), "Bearer xxxxxxxxxxxxxxxxxxx" },
{ HttpRequestHeader.Accept.ToString(), "application/json" },
{ "X-Version", "1" }
},
Content = new StringContent(JsonConvert.SerializeObject(svm))
};
var response = client.SendAsync(httpRequestMessage).Result;
var request = new HttpRequestMessage {
RequestUri = new Uri("[your request url string]"),
Method = HttpMethod.Post,
Headers = {
{ "X-Version", "1" } // HERE IS HOW TO ADD HEADERS,
{ HttpRequestHeader.Authorization.ToString(), "[your authorization token]" },
{ HttpRequestHeader.ContentType.ToString(), "multipart/mixed" },//use this content type if you want to send more than one content type
},
Content = new MultipartContent { // Just example of request sending multipart request
new ObjectContent<[YOUR JSON OBJECT TYPE]>(
new [YOUR JSON OBJECT TYPE INSTANCE](...){...},
new JsonMediaTypeFormatter(),
"application/json"), // this will add 'Content-Type' header for the first part of request
new ByteArrayContent([BINARY DATA]) {
Headers = { // this will add headers for the second part of request
{ "Content-Type", "application/Executable" },
{ "Content-Disposition", "form-data; filename=\"test.pdf\"" },
},
},
},
};
There is a Headers property in the HttpRequestMessage class. You can add custom headers there, which will be sent with each HTTP request. The DefaultRequestHeaders in the HttpClient class, on the other hand, sets headers to be sent with each request sent using that client object, hence the name Default Request Headers.
Hope this makes things more clear, at least for someone seeing this answer in future.
I have added x-api-version in HttpClient headers as below :
var client = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(callingUrl)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-version", v2);
My two cents. I agree with heug. The accepted answer is a mind bender. Let's take a step back.
Default headers apply to all requests made by a particular HttpClient. Hence you would use default headers for shared headers.
_client.DefaultRequestHeaders.UserAgent.ParseAdd(_options.UserAgent);
However, we sometimes need headers specific to a certain request. We would therefore use something like this in the method:
public static async Task<HttpResponseMessage> GetWithHeadersAsync(this
HttpClient httpClient, string requestUri, Dictionary<string, string> headers)
{
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
foreach(var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
return await httpClient.SendAsync(request);
}
}
If you only need one additional non-default header you would simply use:
request.Headers.Add("X-Version","1")
For more help:
How to add request headers when using HttpClient
Also you can use HttpClient.PostAsync method:
using (HttpClient http_client = new HttpClient())
{
StringContent string_content = new StringContent(JsonSerializer.Serialize("{\"field\":\"field_value\"}"));
string_content.Headers.Add("X-Version","1");
using (HttpResponseMessage response = await http_client.PostAsync("http://127.0.0.1/apiMethodName", string_content))
{
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"Response status code: {response.StatusCode}");
}
else
{
Console.WriteLine($"Error status code: {response.StatusCode}");
}
}
}
Just in case someone is wondering how to call httpClient.GetStreamAsync() which does not have an overload which takes HttpRequestMessage to provide custom headers you can use the above code given by #Anubis and call
await response.Content.ReadAsStreamAsync()
Especially useful if you are returning a blob url with Range Header as a FileStreamResult

Categories