Filling Parameter with Attribute [FromForm] with Fiddler - c#

I want to test the following method (generated by swagger) with fiddler:
[HttpPost]
[Route("/webservice/images")]
[SwaggerOperation("UploadImage")]
[SwaggerResponse(200, type: typeof(ResourceIdEntry))]
public virtual IActionResult UploadImage([FromForm] Stream image)
{
return new ObjectResult();
}
I configure Fiddler to send a POST to http://localhost:50352/webservice/images with the Header
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
User-Agent: Fiddler
Host: localhost:50352
Content-Length: 12931
and the body
---------------------------acebdf13572468
Content-Disposition: form-data; name="image"; filename="Test.tif"
Content-Type: image/tiff
<#INCLUDE *C:\...\Test.tif*#>
---------------------------acebdf13572468--
but UploadImage is not even called and I just get a 500 returned. If I remove the image parameter, the Method gets at least called. How do I have to configure fiddler so that the call is resolved correctly?

Checkout the following post around uploading file with web api - https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2
There is no built in media formatter for dealing with multi part form posts. However this is nothing stopping you writing your own so the same logic can be applied to multiple actions, here is a gist example of a custom formatter - https://gist.github.com/Danielku15/bfc568a19b9e58fd9e80

Related

Parse an content-type header from http request stream

I have the contents of an http request saved on disk.
It looks like this:
POST http://test.ca/ 1.1
Accept: application/xml
Content-Type: multipart/form-data; boundary="8942d141-7753-45ab-be3a-53021694e70c"
--8942d141-7753-45ab-be3a-53021694e70c
Content-Type: application/xml Content-Disposition: form-data; name=Bundle
...
--8942d141-7753-45ab-be3a-53021694e70c
Content-Type: image/jpg Content-Disposition: form-data; name="image 1 of 2"; filename=Attachment1.jpg; filename*=utf-8''Attachment1.jpg
...
--8942d141-7753-45ab-be3a-53021694e70c--
Normally, if you were processing this at the time of request, the HttpRequest object would be used to get the content type. If I have that request persisted to disk, are there any available classes I can use to handle parsing the ContentType for me?
Everything else can be parsed using the MultipartReader class, but I'm not aware of anything that will handle parsing the request header, given an instance of a stream. If I don't have to roll my own that would be great.

Uploading multipart form files with HttpClient

I am trying to create an attachment using the Support Bee API as documented here:
https://supportbee.com/api#create_attachment
I have written a service that uses an HttpClient to create and send the request using a filename.
If I test in in Postman, it succeeds. I am using form-data for the body and just selecting the file to upload from the UI:
It doesn't work when I try to upload it via my HttpClient Service:
public async Task<string> CreateAttachmentAsync(string fileName)
{
// "client" is HttpClient provided via D.I.
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StreamContent(new FileStream(fileName, FileMode.Open)), "files[]");
using (HttpResponseMessage response = await client.PostAsync(
"https://xxx.supportbee.com/attachments?auth_token=xxx",
content))
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
This results in a 500 Internal Server Error. Inspecting the MultipartFormDataContent object I can see that it's header values are automatically being set:
{
Content-Type: multipart/form-data; boundary="c9be3778-4de5-4460-9929-adcaa6bdda79"
Content-Length: 164
}
I have also tried reading the file to a byte array first and using ByteArrayContent instead of StreamContent to no avail. The response doesn't provide anything helpful, but since the request works in Postman I must have something wrong with my code, but I don't know what else to try.
Edit: I tested with Fiddler to compare the successful Postman request to my code. Here is the request with Postman:
POST
https://xxx.supportbee.com/attachments?auth_token=xxx
HTTP/1.1 User-Agent: PostmanRuntime/7.22.0 Accept: / Cache-Control:
no-cache Postman-Token: f84d22fa-b4b1-4bf5-b183-916a786c6385 Host:
xx.supportbee.com Content-Type: multipart/form-data;
boundary=--------------------------714700821471353664787346
Accept-Encoding: gzip, deflate, br Content-Length: 241 Connection:
close
----------------------------714700821471353664787346 Content-Disposition: form-data; name="files[]"; filename="sample.txt"
Content-Type: text/plain
This contains example text.
----------------------------714700821471353664787346--
And the failing request from my code:
POST
https://xxx.supportbee.com/attachments?auth_token=xxx
HTTP/1.1 Host: xxx.supportbee.com Accept: / Accept-Encoding:
gzip, deflate, br Connection: close Content-Type: multipart/form-data;
boundary="ea97cbc1-70ea-4cc4-9801-09f5feffc763" Content-Length: 206
--ea97cbc1-70ea-4cc4-9801-09f5feffc763 Content-Disposition: form-data; name="files[]"; filename=sample; filename*=utf-8''sample
This contains example text.
--ea97cbc1-70ea-4cc4-9801-09f5feffc763--
The difference I can see is that the individual part in Postman has its own Content-Type: text/plain header for the file, and mine doesn't. I'm unable to add this because if I try content.Headers.Add("Content-Type", "text/plain"); It fails with 'Cannot add value because header 'Content-Type' does not support multiple values.'
First, it's important to note that a 500 response is akin to an unhandled exception, i.e. it's a bug on their end and more or less impossible to know for sure what you did wrong. I would suggest reporting it to them and, although I'm not familiar with Support Bee, I would hope they have good support people who can help you troubleshoot. :)
But if you want to play the guessing game, I agree that subtle differences between your successful Postman call and your code are a good place to start. For that header, note that content is the MultipartFormDataContent. You actually want to set it on the StreamContent object.
Also, look at the request headers Postman is sending and see if Content-Disposition includes a filename. You might need to add that to your code too, if the API is expecting it.
Here's how to do both:
var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
content.Add(fileContent, "files[]", Path.GetFileName(path));
If that's not the problem, look at the "raw" version of the request body in Postman, as well as those 11 request headers, and see if you can spot anything else you might be missing.

How to make multipart/mixed request containing nested HTTP requests

I am trying to implement creating a multipart request where each part is a HTTP request
To see what I mean here's for example how this Google API works: https://cloud.google.com/dns/api/batch#example (I don't use that API, it's just an example)
I've seen examples using MultipartFormDataContent but I don't understand how to create each part"
--====1340674896===
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1111
POST /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
The content of each part is I think the serialized string of a request:
GET /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
So how do I create this? I guess I need to get the serialized version of a HttpRequestMessage?
Can I just serialize request.Content.ReadAsStringAsync())
In WebAPI I see there's this HttpContentMessage which takes a HttpRequestMessage and can serialize it:
var httpMessageContent = new HttpMessageContent(request);
var buffer = httpMessageContent.ReadAsByteArrayAsync().Result;
stream.Write(buffer, 0, buffer.Length);
But I don't have this class available in .NETStandard

[FromBody]JToken param is null when ContentType: application/json or it's bad serialized when Contenttype: application/x-www-form-urlencoded [Fiddler]

As the topic says, I've faced with a problem while trying to call an endpoint (POST) with a Request Body via Fiddler.
There is a http api method:
[HttpPost]
[Route("books")]
public IHttpActionResult GetBooks([FromBody]JToken filterRequest)
{...}
In Fiddler I make a POST call with request header:
User-Agent: Fiddler
Host: localhost
Content-Length: 21
Content-Type: application/json
And the Request Body looks like: { "title" : "Harry Potter"}. While debugging it, I get null filterRequest parameter.
But when I use Content-Type: application/x-www-form-urlencoded, parameter filterRequest parameter is not null but unfortunately contains incorrect syntax like:
{{"{ \"title\" : \"Harry Potter\"}": ""}}
And it's wrong serialized by:
var columnsFilter = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(filter);
I have no idea what I am doing wrong here. Maybe do you have met with similar problem and could help?
It turned out that the whole problem was based on wrong quotes. I had to use just ' and the posted request body was correct with Content-Type: application/json.

ASP.NET WebAPI - Issues with [FromBody]

I'm looking to implement a new API but rather than going down my usual route of PHP I've opted for C#.
I've had a little play with the 'MVC 4 API' example, but so far I can't seem to get my requests working.
I've created a controller called 'Values' and have the following method:
[HttpPost]
public void Post([FromBody]string value)
{
string body = value;
}
I've then sent the following POST request via fiddler to said API:
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 10
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
value=test
After running this, it looks as though the method is being called, but when attempting to get the 'value' sent through the body, it doesn't seem to pick up on it and instead gives me a null.
I can't seem to make it work for Content-Type: application/x-www-form-urlencoded, but this should work meanwhile :)
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 6
Content-Type: application/json; charset=UTF-8
"test"
So I found out that if you need to make it work with application/x-www-form-urlencoded then you only need to pass =value as the body of your request. Definitely weird, but I guess this is not MVC, it's WebApi, so you shouldn't be passing application/x-www-form-urlencoded anyway ;)

Categories

Resources