How to corectly set the ContentType property in HttpWebRequest (or how to fix the missing Content-Type header) - header

I thought I'd share something that took me some time to figure out:
I wrote a simple Post method using HttpWebRequest class.
In HttpWebRequest you can't use HttpWebRequest.Headers collection to set your desired headers when there is a dedicated property for it - you must use that dedicated property. ContentType is one of them. So I created my HttpWebRequest like this:
HttpWebRequest httpWebRequest = (HttpWebRequest)webRequest;
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = false;
httpWebRequest.ServicePoint.Expect100Continue = false;
httpWebRequest.ContentType = "application/json";
somewhere below I set the body of my request like this:
using (StreamWriter streamWriter = new StreamWriter(streamWebRequest))
{
streamWriter.Write(sJson);
}
and posted the request using:
WebResponse webResponse = httpWebRequest.GetResponse();
But I kept getting a "400 - Bad Request" error, while the same request worked from Postman. After analyzing the request with Fiddler I found that when I send the request from my app, the Content-Type: application/json header is missing. All the other headers were present, except for Content-Type. I thought I'm setting it wrong, so I googled but didn't find a good answer. After much experimentation I found, that if I move the line:
httpWebRequest.ContentType = "application/json"
after this block:
using (StreamWriter streamWriter = new StreamWriter(streamWebRequest))
{
streamWriter.Write(sJson);
}
then the httpWebRequest.ContentType = "application/json" header finally appears in the request. So, for HttpWebRequest make sure you always set your HttpWebRequest's body/content first, before you set the ContentType property.
Hope it helps

My question above already has the answer, but to mark it as "Answered" I had to add this comment:
Make sure you always set your HttpWebRequest's body/content first, before you set the ContentType property.This way the "Content-Type" header will appear in the request.

Related

BIM 360 Field API Issues V1: GET Request works perfectly with Postman, responds "Unauthorized" with RestSharp

Trying to implement var client = new RestClient("https://bim360field.autodesk.com/fieldapi/checklists/v1/06eede44-a707-4f0b-9529-78abea6e6bf5");
var request = new RestRequest(Method.GET); https://bim360field.autodesk.com/apidoc/index.html#fieldapi/checklists/v1/checklists_api_method_2 in my C# solution.
I've set up an example Get Request in Postman. Works perfectly with the form-data, x-www-form-urlencoded, no auth, bearer token.
Tried to copy the exact Restshap Request code from Postman to my C# app. Does not work; always responds with "Unauthorized". Tried changing cookie mngmt, and auth window/nltm mngmt. Did not help.
var request = new RestRequest(Method.GET);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Connection", "keep-alive");
request.AddHeader("Content-Length", "91");
request.AddHeader("Accept-Encoding", "gzip, deflate");
request.AddHeader("Cookie", "OPTOUTMULTI_REF=b7027893-8564-4b33-8f1e-de0c175d38c6; OPTOUTMULTI_GEO=NL; utag_main=v_id:016639c85215001e1ab9f566c61201090006808800bd0$_sn:4$_ss:0$_st:1545042741235$ses_id:1545040922510%3Bexp-session$_pn:1%3Bexp-session; XSRF-TOKEN=YxM2BdzM19rML7OjKGZqcD0hAqv%2F225McEm8oB3m7No%3D; 75da74d446a8376e2cf6a286ff63573ab705f04c36540fdda21c1dbc1928d4e72cabf30a63e339690e88fc3801a93e44e6e3ddc20651f602d2c5eaaf49b21d61=f795a05c211085d994bf2e08996ff747");
request.AddHeader("Host", "bim360field.autodesk.com");
request.AddHeader("Postman-Token", "0b3c652d-462c-4aba-a661-476309792018,b4d4846c-a928-406f-837c-f16809a9bccd");
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Accept", "*/*");
request.AddHeader("User-Agent", "PostmanRuntime/7.15.2");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"ticket\"\r\n\r\n{API_TICKET}\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"project_id\"\r\n\r\n049bf984-b8d1-4330-a17c-0832c6facf49\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);```
I expect that this code is also working with Restsharp. Do I miss anything?
For your cookies you will need to setup a CookieContainer on your Client.
Client = new RestClient(Request.GetEnvironment())
{
CookieContainer = new System.Net.CookieContainer()
};
You don't need the Postman Token. You will want to use the Bearer Token provided by your API to make the call and add it to your headers or parameters.
When intializing RestClient you only want to pass the base url. Then pass the rest of your api path during the RestRequest initialization. This will help for future use when wanting to hit more than one end point with the same cookies.
Here is a working example for you:
// (1) Build request
var client = new RestClient();
client.BaseUrl = new System.Uri("https://bim360field.autodesk.com/");
// Set resource or end point
var request = new RestRequest();
request.Resource = "/fieldapi/checklists/v1";
request.Method = Method.GET;
// Add parameters
request.AddParameter("ticket", "{API_TICKET}");
request.AddParameter("project_id", "049bf984-b8d1-4330-a17c-0832c6facf49");
// (2) Execute request and get response
IRestResponse response = client.Execute(request);
Hope it helps!

restsharp get error (authentication)

I have a API GET call that works in postman BUT not in VS2017. I copied the code
from postman:
var client = new RestClient("http://server- d01:9000/amp/portal/api/dougtest/v1");
var request = new RestRequest(Method.GET);
request.AddHeader("Postman-Token", "19763da3-4b00-4e92-83e0-1ac75f99d219");
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("X-XSRF-TOKEN", "71cf12361-8090-499a-adc3-2d5e98a04143");
request.AddParameter("undefined", "{\n \"username\":\"domain\\\\username\",\n \"password\":\"myPasswd\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
The error I am getting is unauthorized, the API required a header of X-XSRF-TOKEN with a value of 71cf12361-8090-499a-adc3-2d5e98a04143 (a fake key)
Using postman, everything works just fine, but using VS2017 I get an error:
{"status":"unauthorized","error":"Login is required","errormsg":null}
What's weird (I am new to this so pardon my ignorance)is that the header does not contain:
request.AddHeader("X-XSRF-TOKEN", "71cf12361-8090-499a-adc3-2d5e98a04143");
but rather the parameter does, which is confusing since I thought the AddHeader would add it to the header but maybe I am misunderstanding something....
any advice/suggestions would be extremely welcomed
thank you in advance
dougc
Please use the below code and check
var client = new RestClient("http://server- d01:9000/amp/portal/api/dougtest/v1");
var request = new RestRequest(Method.GET);
//Make sure to give the Valid Token
request.AddHeader("Authorization","X-XSRF-TOKEN <<Generated Token>>");
IRestResponse response = client.Execute(request);
Console.WriteLine("Response :" + response.Content);

how to add 'Content-Type' header in (HTTP GET) Rest request header collection using HttpClient?

I am using HttpClient for rest service . At at one point I have a problem when I try to add "Content-Type" in my 'Get' request header .
I know "Content-Type" is suitable for content send in request body part But It's my need i have to send "Content-Type" with request header part.
I also try to remove "Content-Type" header from Invalid Header list of HttpRequestHeaders
I find link How do you set the Content-Type header for an HttpClient request?
Dim field = GetType(System.Net.Http.Headers.HttpRequestHeaders).GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.[Static])
If field IsNot Nothing Then
Dim invalidFields = DirectCast(field.GetValue(Nothing), HashSet(Of String))
invalidFields.Remove("Content-Type")
End If
But my issue not resolved I have exception
InnerException:
Message=The 'content-type' header must be modified using the appropriate property or method.
StackTrace:
at System.Net.WebHeaderCollection.ThrowOnRestrictedHeader(String headerName)
at System.Net.WebHeaderCollection.Add(String name, String value)
at System.Net.Http.HttpClientHandler.SetRequestHeaders(HttpWebRequest webRequest, HttpRequestMessage request)
at System.Net.Http.HttpClientHandler.CreateAndPrepareWebRequest(HttpRequestMessage request)
at System.Net.Http.HttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
InnerException:
I find some tools like Postman or SoupUI allow this .
Please help me to find some solution .
Thanks
HttpWebRequest may come to your rescue.
private static string CallService(string url)
{
WebRequest req = WebRequest.Create(url);
req.Method = "GET";
String json;
req.ContentType = "application/json; charset=utf-8";
var resp = req.GetResponse();
using (varstream = resp.GetResponseStream())
{
var re = new StreamReader(stream);
json = re.ReadToEnd();
}
return json;
}
}
Async implementation of this can be found from Getting the Response of a Asynchronous HttpWebRequest

How to set Content-Type header in a http get response using C#'s HttpClient?

I am having problems in retrieving the contents of a http get request in the proper charset.
I tried several pieces of code, such as the following:
HttpClient h = new HttpClient();
//Content-Type: text/html; charset=UTF-8
//p.s. contents are in hebrew.
var resp = h.GetAsync("http://www.wnf.co.il");
var content = resp.Result.Content;
//remove the default Content-Type header
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "text/html; charset=utf-8");
var res = content.ReadAsStringAsync();
var s = res.Result;
Console.WriteLine(s);
which still does not help, I still get the content in wrong encoding.
This post clarifies that setting the header's request headers charset will not help, it's the response's one that needs to be set. (Besides, you will get an error in trying to add
header "Content-Type" to a request Header.)
But I still could not end up with working retrieval of the content in the proper charset (utf-8).
What am I missing ?
I have been doing similar stuff with hebrew sites for a while, in comparing the response's header in Fiddler from this site and others where I do not have this problem - the only difference I see is indeed this Content-Type header in the response.
The issue is probably due to this bug:
https://connect.microsoft.com/VisualStudio/feedback/details/790174/system-net-http-httpcontent-readasstringasync-does-not-handle-imperfect-content-type-headers
The work-around is to get the response as a byte array and encode it yourself:
var bytes = await content.ReadAsByteArrayAsync();
var s = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
As a side-note, is there a reason you're using .Result instead of await? You are blocking the current thread unnecessarily and setting yourself up for deadlocks.

Adding Header to Web Request throws an error

When attempting to add a value to the header of an HTTP request, I get the following error:
Specified value does not have a ':' separator. Parameter name: header
To add the header I am using the following code:
Dim request As HttpWebRequest = WebRequest.Create(url)
Dim soapXML As New XmlDocument()
soapXML.LoadXml(soapEnvelope)
request.Headers.Add("SOAPAction", action)
request.Method = "POST"
request.ContentType = "text/xml;charset=""utf-8"""
request.Accept = "text/xml"
Using stream As Stream = request.GetRequestStream()
soapXML.Save(stream)
End Using
I have been looking all over the place and haven't found anybody who has had any similar errors, outside of this SO question: using httpRequest headers?
Which didn't help much.
Does anybody know what I might be doing wrong here?
EDIT 1: Added all the code that I currently have that creates my web request.