Al: HttpHeaders - Content-type - "application/x-www-form-urlencoded' Issue

Created on 4 Apr 2018  路  5Comments  路  Source: microsoft/AL

I believe there is a bug here with httpheaders - I keep getting the following error:

"Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."

I'm on the latest dev preview release.
I've used a few different variations of adding this as a header to client by using AdddDefaultHeaders, on the httpRequestMessage.GetHeaders(headers) this was with httpclient.Send, also by using the httpContent.GetHeaders(headers) this was using the httpclient.Post.

here is sample code using HttpClient.Send:

gcontent: HttpContent;
gHttpClient:HttpClient;
gheaders:HttpHeaders;
greqMsg:HttpRequestMessage;
gResponseMsg:HttpResponseMessage;
ltext:Text;

ltext:= 'scope=APIServices&grant_type=client_credentials';
    gcontent.WriteFrom(ltext);
    greqMsg.SetRequestUri(lurl);
   gheaders.Add('content-type', 'application/x-www-form-urlencoded');
   gheaders.Add('accept','application/Json');
   gheaders.Add('authorization','Basic '+ lbase64key);
   greqMsg.Content(gcontent);

    greqMsg.GetHeaders(gheaders);
    greqMsg.Method :=  'post';

    if not gHttpClient.Send(greqMsg,gResponseMessage) then
        Error('API Authorization token request failed...');

I should mention that once I remove the content-type from headers and post/send either or I can get past the call but API rejects the request with 400 because it wants that content-type.

question

Most helpful comment

@thpeder,
I confirm after doing what you suggested now I'm able to get past the issue. I ran into another issue with being unable to read response content in the global variable but I had a solution to this problem which was provided by @ajkauffmann in his previous blog posts. So all is working great now! Thanks for the help everyone! 馃憤

All 5 comments

Hi @tkane823,
By default the content headers (gcontent.GetHeaders(...)) already contains a header for 'Content-Type' namely 'text/plain; charset=utf-8' so if you remove that one first then you should be able to set the other content-type and send the request.

Another thing to keep in mind is to not mix content headers and message headers. They are set using different objects.

The content-type header must be set on the HttpContent object.
The accept and authorization headers must be set on the HttpMessage object.

Hi @thpeder and @ajkauffmann

Thanks for taking the time to respond so quickly! I did what you both suggested and I'm still running into the same issue. Below I have two snippets one that uses the POST method and one with SEND. I've tried about a few variations with both cases but I able to reproduce the same error.

SEND

gcontent: HttpContent;
gHttpClient:HttpClient;
gheaders:HttpHeaders;
greqMsg:HttpRequestMessage;
gResponseMsg:HttpResponseMessage;
ltext:Text;
lheaders:HttpHeaders;

ltext:= 'scope=APIServices&grant_type=client_credentials';
gHttpClient.DefaultRequestHeaders.Remove('Content-Type');
gcontent.Clear();

    gcontent.WriteFrom(ltext);
    greqMsg.SetRequestUri(lurl);
    gheaders.Clear();
    lheaders.Clear();

   gcontent.GetHeaders(lheaders);
   lheaders.Remove('Content-Type');
   lheaders.Add('Content-Type', 'application/x-www-form-urlencoded');
   gcontent.GetHeaders(lheaders);

   greqMsg.GetHeaders(gheaders);
   gheaders.Remove('Content-Type');
   gheaders.Add('accept','application/Json');
   gheaders.Add('authorization','Basic '+ lbase64key);
   greqMsg.Content(gcontent);

    greqMsg.GetHeaders(gheaders);
    greqMsg.Method :=  'post';

    if not gHttpClient.Send(greqMsg,gResponseMessage) then
        Error('API Authorization token request failed...');

POST

gcontent: HttpContent;
gHttpClient:HttpClient;
gheaders:HttpHeaders;
greqMsg:HttpRequestMessage;
gResponseMsg:HttpResponseMessage;
ltext:Text;
lheaders:HttpHeaders;

ltext:= 'scope=APIServices&grant_type=client_credentials';
gHttpClient.DefaultRequestHeaders.Remove('Content-Type');
gHttpClient.DefaultRequestHeaders.Add('Authorization','Basic '+ lbase64key);
gHttpClient.DefaultRequestHeaders.Add('Accept','application/Json');
gcontent.Clear();

    gcontent.WriteFrom(ltext);
    lheaders.Clear();

   gcontent.GetHeaders(lheaders);
   lheaders.Remove('Content-Type');
   lheaders.Add('Content-Type', 'application/x-www-form-urlencoded');
   gcontent.GetHeaders(lheaders);

    if not gHttpClient.Post(lurl,gcontent,gResponseMsg) then
        Error('API Authorization token request failed...');

In the post method it doesn't accept a request message parameter so I'm assuming it's using the httpclient's default request, so I added the default request header for authentication and accept there. In both ways I get the same error. I've also tried to have the same headers for requestmessage headers and content headers with same result.

Thanks!

@tkane823, if you remove the calls to gHttpClient.DefaultRequestHeaders.Remove and gheaders.Remove then it works for me.

@thpeder,
I confirm after doing what you suggested now I'm able to get past the issue. I ran into another issue with being unable to read response content in the global variable but I had a solution to this problem which was provided by @ajkauffmann in his previous blog posts. So all is working great now! Thanks for the help everyone! 馃憤

Was this page helpful?
0 / 5 - 0 ratings