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

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

Related

How to corectly set the ContentType property in HttpWebRequest (or how to fix the missing Content-Type 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.

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!

Setting REQUEST header Http Client vb.net

Consider the following VB code:
Public Async Function someFunction(ByVal url As String, Optional ByVal methodPost As Boolean = False, Optional ByVal postContent As HttpContent = Nothing) As Threading.Tasks.Task(Of String)
Using client = New HttpClient
client.DefaultRequestHeaders.Authorization = makeAuthenticationHeader()
If methodPost Then
client.DefaultRequestHeaders.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
Dim Response = Await client.PostAsync(url, postContent)
Dim content As String = Await Response.Content.ReadAsStringAsync
Return content
Else
Return Await client.GetStringAsync(url)
End If
End Using
End Function
I want to set the request content type to application/json as well as the response content type to application/json.
If I add the following line of code:
client.DefaultRequestHeaders.Add("content-type", "application/json") then the system throws an exception Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects..
I've searched all over google for a way to set the requests header to JSON. Using fiddler (on the server) I can see that the request is sent as plain/text.
POST **URL REMOVED FOR SAFETY REASONS** HTTP/1.1
Authorization: Basic **HASHED AUTH DETAILS - REMOVED FOR SAFETY REASONS**
Accept: application/json
Content-Type: text/plain; charset=utf-8
Host: **HOST REMOVED FOR SAFETY REASONS**
Content-Length: 1532
Expect: 100-continue
Connection: Keep-Alive
Content-Type: text/plain; charset=utf-8 This is where I am having an issue. This needs to be set to a content type for JSON as the body of the request is JSON. How do I set this content-type to JSON in vb.net Code.
I found a solution, I don't know if it is the correct solution or if there is a better solution out there.
Basically you need to set the content-type header on the actual content that you are sending and not on the HTTP Client.
So basically adding content.Headers.ContentType = New MediaTypeWithQualityHeaderValue("application/json") to your code should set the REQUEST's content-type to JSON as well.
Public Async Function someDifferentFunction() As Threading.Tasks.Task(Of String)
Dim url As String = "http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Dim content As HttpContent = New StringContent(txtRequestBody.Text)
content.Headers.ContentType = New MediaTypeWithQualityHeaderValue("application/json")
Return Await someFunction(url, True, content)
End Function

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.

Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter

I'm writing a web API that has a post method accepting files uploaded from UI.
public async Task<List<string>> PostAsync()
{
if (Request.Content.IsMimeMultipartContent("form-data"))
{
string uploadPath = HttpContext.Current.Server.MapPath("~/uploads");
var streamProvider = new MyStreamProvider(uploadPath);
await Request.Content.ReadAsMultipartAsync(streamProvider);
return streamProvider.FileData
.Select(file => new FileInfo(file.LocalFileName))
.Select(fi => "File uploaded as " + fi.FullName + " (" + fi.Length + " bytes)")
.ToList();
}
else
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid Request!");
throw new HttpResponseException(response);
}
}
Then I post a request for the above action by postman.
I set the content-type header to multipart/form-data
but an error occurred during the execution of action.
here is the error message body :
"Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter.\r\nParameter name: content"
I went to the postman headers but I found that the request header content type was set to application-json.
You are looking on the response header which is json format and this is ok for you.
Your real problem is with the postman request, so just remove the 'Content-Type: multipart/form-data' entry from request header.
It's enough to upload a file as form-data and send the request.
Look what happen when you set the Content-Type manually vs. when you not:
Postman knows to set both the content type and boundary, since you set only the content type
First: Postman have a bug in handling file-based requests.
You can try adding this to your WebApiConfig.cs it worked for me:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();