c# httpclient PostAsJson sending GET request instead of POST - c#

I am using HttpClient to make a post request. I get back 405 method not allowed. When capturing a trace in fiddler, it goes out as GET instead of POST!
using (var client = new HttpClient())
{
var url = AppSettingsUtil.GetString("url");
var response = client.PostAsJsonAsync(url, transaction).Result;
}
I am aware of the async/await issues. This is a simplified sample to show the issue.
Is there some sort of web.config or machine.config setting that could be affecting this? Other requests (sent through RestSharp) send Posts correctly
Here is what fiddler captures. Rerunning the trace in fiddler also returns the 405 (as expected). Manually switching it to POST and running works from fiddler.
Also, perhaps because the method was switched to GET, there is no body captured in fiddler, I had to manually paste in the JSON
GET /*URL*/ HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: /*host*/
Connection: Keep-Alive

The problem appears to be that someone changed the URL without telling us, and they put a redirect in place. HttpClient is responding to the redirect, but ends up actually sending the request to the final destination as a Get.
This seems like a bug in HttpClient to me, that it should either send the ultimate request as a Post, or throw an exception saying it can't do what I asked it to.
See Forwarding a response from another server using JAX-RS

Related

Change request Content-Type to allow invalid/unsupported request Content-Types

A client is currently sending our ASP.NET 4.x/Core REST APIs the correct request payload but invalid request Content-Type which is resulting in 415 status codes being returned. Obviously the client sending the invalid Content-Type is an issue but I'd like to consider a server side fix as an interim solution.
One solution which seems to resolve the issue is to modify the request Content-Type in the middleware as an example shown below:
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers["Content-Type"] == "invalid json header")
{
context.Request.Headers["Content-Type"] = "application/json";
}
}
However I'm wondering if there's a better/more elegant solution that doesn't involve adding extra middleware?
Edit: another potential solution is to add application/octet-stream to JsonFormatter.SupportedMediaTypes which is what the Content-Type defaults to in cases where its omitted/invalid but I think this will force application/octet-stream requests to read as application/json requests which isn't ideal either as we do get media upload requests with application/octet-stream as Content-Type
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));

HttpWebRequest.Headers are missing some headers

I iam working on a tool that let users check their API. One of the features is to show the actual send request headers.
Iam having trouble getting these headers though as the Headers property doesnt seem to include them all. I tried looking at tracelisteners but these seem to be more oriented to debugging and the config is global so it applies to all webrequests send by the app which is not what I want.
When I run this code on net48 (in core I seem to get 0 headers back):
// Create a new 'HttpWebRequest' Object to the mentioned URL.
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://www.contoso.com");
// Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
Console.WriteLine("\nThe HttpHeaders are \n\n\tName\t\tValue\n{0}",myHttpWebRequest.Headers);
I get the following output
The HttpHeaders are
Name Value
Host: www.microsoft.com
However in fiddler and with trace listeners I see these headers:
Host: www.contoso.com
Connection: Keep-Alive
Why can't I see the Connection header?
Now I see there is some redirecting going on. WebRequest seems to only show the headers send in the LAST request which didn't had the Connection header.

What does a curl_error_56 and a HTTP_error_502 have in common?

I am working on a Chatbot in Slack that sends a POST request to http://localhost:44331/values/api an .NET Core API that i built in C#. In the Post request is a response_url in the body I can use to send back the needed information.
So I have been trying to make this work for about two weeks now and used a fiddler and to mimic the request so I can make some changes on the body and the headers to see if that makes a difference.
So after a lot of errors I have come to two specific errors that haven't changed for a long while.
sent with the Slack Chatbot: curl_error_56
There really isnt much I can change in this matter except the url I want to send the request to.
In fact this request has never even reached the post method in my API.
Thats what the Slackbot answers
sent with fiddler: HTTP error 400
I used Requestbin to get the information that has been sent by the bot and copied it into the composer in fiddler.
I am a total novice to Web programming in any kind of way so I really don't know what they have in common.
Are those errors coming because I am using localhost?
What am I missing?
here is the request so you can copy it if needed
host: localhost:44331
Accept: application/json,*/*
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
User-Agent: Slackbot 1.0 (+https://api.slack.com/robots)
X-Slack-Request-Timestamp: 1569238196
X-Slack-Signature: v0=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Length: 381
Connection: keep-alive
Alright I got some help by a friend and he explained to me that Slack is unable to access my localhost, because it is not a local app. It is taking its information from the web and making it send a request to my localhost is useless because it is not a static IP.
What i need is an Endpoint.
I can get one by requesting it from my ISP (Internet Service Provider) or getting myself a server which already has an static IP.
Thanks for any help you wanted to provide.

HttpClient with WebRequestHandler returns invalid cached response

We have stumble unto a problem while using WebRequestHandler and HttpRequestCachePolicy where the cached entry seems to get corrupted after a precise sequence. The scenario goes as follow:
request returns a 200 response with Cache-Control: public, must-revalidate, max-age=0 and Last-Modified.
a second request is made with Last-Modified-Since that returns a 500 response with Cache-Control: private. In our case, it is caused by the IIS server when an error occurs during the request.
a third request is sent. It contains a Last-Modified-Since header which causes the server to respond with 304.
The HttpClient result resolves to the 500 response.
My assumption is that the Last-Modified-Since header in the 3rd request should not have been present and is a bug.
The test was made in a sample console application in .NET 4.5 while using the HttpRequestCacheLevel.Default cache policy. Trying the same test in a browser doesn't seem to reproduce the problem when navigating to the URL (I verified that max-age=0 was not present in the request).
What I am trying to understand is if it's a bug in the .NET framework, if we didn't use the API correctly or if we didn't use the response headers correctly.

C# WSDL Client Request Packages

I am currently adding a SOAP-WSDL Service to my project using "Add Service Reference". it creates all necessary classes and functions for me to call. Some of these functions dont give me a response. After 1 minute delay i get a timeout exception. However when i forge the request using Postman (a chrome extension for making network requests) it gets full response. i got suspicious and started to inspect network using Wireshark. after inspection i saw that problem was at the service. but i can't make them fix that. so i need to imitate Postman request using C#.
Main difference between mine and postman is, Postman posts all necessary data in single request for a response, but my client posts just http headers waits for a Http Continue and continues sending necessary data. i guess this breaks the service.
Here are wireshark screenshots for Postman and my client
(Postman is on the left of image and right one is my .net client - sorry for my perfect paint skills)
Is there any configuration on .net wsdl client with basicHttpBinding i can configure to make single request for a call?
edit: when i further investigated my C# client i saw that .net http layer send an initial POST with saying (Expect: 100 Continue), after it receives continue it continues to send SOAP Envelope
edit2: i changed my code to issue request using HttpWebRequest, but .net still sends header and post body with seperate requests (even when i disabled Expect: 100 Continue) and in my theory this breaks service.
question2: is there anyway to say HttpWebRequest, don't split header and body? send all of them in single request?
edit3: i solved the problem. but it wasn't about 100 Continue. service was being broken because of missing User-Agent Header
For HttpWebRequest you can add the following to your .config file - we use this on our service. I'm not, however, sure how it impacts WCF channels.
<configuration>
<system.net>
<settings>
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
</configuration>
i finally solved the problem. after long inspections and tries i saw that remote service stops responding in the middle of the data communication if i dont add User-Agent HTTP Header. so i added http header using IClientMessageInspector before every request
here is wcf code if anybody needs it
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty realProp;
object property;
//check if this property already exists
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out property))
{
realProp = (HttpRequestMessageProperty) property;
if (string.IsNullOrEmpty(realProp.Headers["User-Agent"])) //don't modify if it is already set
{
realProp.Headers["User-Agent"] = "doktorinSM/2.1";
}
return null;
}
realProp = new HttpRequestMessageProperty();
realProp.Headers["User-Agent"] = "doktorinSM/2.1";
request.Properties.Add(HttpRequestMessageProperty.Name, realProp);
return null;
}

Categories