'HttpRequest works in postman but not in .Net Core
So, I have a POST request to upload a file. I'm able to do that request inside a postman with simple settings like this: Body: form-data, body has only one item. Key=file, Value=xxxx.pdf
No authorization. Final working request from postman console looks like this:
Request Headers
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: 8d5df709-8f9e-48e2-bf20-f300b24d4be8
Host: api.xxxx.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=--------------------------138420394858496796018969
Cookie: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Length: 976797
Request Body
file: undefined
This works and file gets uploaded. But when I do the same thing in .net Core, it fails every time (400 - bad request)
using (var message = new HttpRequestMessage(HttpMethod.Post, uploadUri))
{
using (var fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
using (var formDataContent = new MultipartFormDataContent())
{
using (var fileContent = new StreamContent(fileStream))
{
formDataContent.Add(fileContent, "file");
message.Content = formDataContent;
using (var response = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
}
}
}
}
Edit: Only difference that I can see is the content-disposition header being added to StreamContent. Hovewer I was not able to remove this header.
Edit: After a talk with the developer of the API, the problem is 100% the body & headers of the request. Api does not want a content-disposition header and excpects body multipart/form-data with pair file=byteArray
Solution 1:[1]
So in the end. It was Oliver from comments who pointed me in a right direction and with Fiddler I found the solution. The problem was in a content-type header. When this header is generated in postman, boundary is without quotation marks. Httpclient hovewer adds those automaticaly. These were the reason why my request was being rejected.
Working code:
using (var message = new HttpRequestMessage(HttpMethod.Post, uploadUri))
{
var boundary = $"--------------------------{Guid.NewGuid().ToString("N").ToUpper()}";
using (var fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
using (var content = new MultipartFormDataContent(boundary))
{
content.Headers.Remove("Content-Type");
content.Headers.TryAddWithoutValidation("Content-Type", $"multipart/form-data; boundary={boundary}");
using (var fileContent = new StreamContent(fileStream))
{
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
fileContent.Headers.ContentDisposition.Name = "\"file\"";
fileContent.Headers.ContentDisposition.FileName = $"\"{fileInfo.Name}\"";
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(fileContent);
message.Content = content;
using (var response = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead))
{
.....
}
}
}
}
Solution 2:[2]
Might be security issue, try to add this before HTTP request code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
Solution 3:[3]
I do believe you're missing Content-Type header value set:
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
I've tested with a *.jpg file and it works OK:
using (var multipartFormContent = new MultipartFormDataContent())
{
//Load the file and set the file's Content-Type header
var fileStreamContent = new StreamContent(File.OpenRead(filePath));
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
//Add the file to form
multipartFormContent.Add(fileStreamContent, name: "file", fileName: filePath);
//Send it
var response = await new HttpClient().PostAsync("http://localhost:5000/[Controller]/[Action]", multipartFormContent);
response.EnsureSuccessStatusCode();
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | DavidWaldo |
| Solution 2 | Bharat Bhushan Sharma |
| Solution 3 |
