2

I am looking to receive 1 CNCTask class object from the body, but I also need to transfer a file in the same POST request. I have written out my POST route definition as:

[HttpPost("TaskUpload")]
[Consumes("application/json")]
public async Task<ActionResult<CNCTask>> Post([FromBody] CNCTask task, IFormFile file)

With my route defined as such, I just don't get how I will even transfer the file (e.g. when testing from Postman). A file would usually be sent in the body (I think ?), but if I already have my CNCTask object being selected by the [FromBody], how do I negotiate this file transfer as well ?

I'm quite confused as to how to send both the class object and the file. Any tips would be appreciated.

EDIT

text body request that only includes a CNCTask object

{
  "description":"truc",
  "completion":24,
  "machine":{
    "hostname":"some host",
    "port": 1234
  }
}

form-data body request that includes the full Payload (CNCTask + IFormFile)

Form-data

Serge
  • 40,935
  • 4
  • 18
  • 45
JetsON
  • 23
  • 5
  • Does this answer your question? [Upload files and JSON in ASP.NET Core Web API](https://stackoverflow.com/questions/41367602/upload-files-and-json-in-asp-net-core-web-api) – Christoph Lütjen Oct 01 '21 at 19:40

2 Answers2

1

This was tested using a Postman and Visual studio.

You have to create a model class

public class CNCTask
{
        public string Description { get; set; }
        public int Completion { get; set; }
        public Machine Machine { get; set; }
        public IFormFile File { get; set; }
}

public class Machine
{
        public string Hostname { get; set; }
        public int Port { get; set; }
}

action

[HttpPost("TaskUpload")]
public async Task<ActionResult<CNCTask>> Post(CNCTask model)

and you can test it using postman

enter image description here

Serge
  • 40,935
  • 4
  • 18
  • 45
  • Right, thanks for that. When actually testing my request in Postman, how would I want to build my client-side request? Also to note is that `CNCTask` itself also has a parameter of type `IMachine` (class object). – JetsON Oct 01 '21 at 19:48
  • @JetsON Try both [FromBody] and [FromForm] attributes if you test from postman, and add multipart/form-data header – Serge Oct 01 '21 at 19:57
  • Would you recommmend sticking to this custom model or using a `JObject` like shown in this answer ? This looks pretty simple to use. https://stackoverflow.com/a/37298083/16938804 – JetsON Oct 04 '21 at 19:23
  • @JetsON I would never use JObject since it is untyped. You will have to convert using json serializer to c# . As a matter of fact , all data is arriving as JObject to action. But when you put a concrete class as input parameter, C# convert this for you automaticaly. I don't see what you can gain , since you will have to write some extra code. And plus it is a very bad programming style. Nobody ever uses it. Only in a very special cases where there is no any another way. Do you still have any problem? – Serge Oct 04 '21 at 19:30
  • @JetsON you can even use httprequest to get input parameters . See my answer https://stackoverflow.com/a/69406588/11392290. But why do this if there are much easier and clear ways. – Serge Oct 04 '21 at 19:40
  • My issue is that I have an object within an object. My `CNCTask` object contains a custom `Machine` class, so I'm struggling to figure out how I will properly extract data properly from my body's `form-data` and build the `Machine` object then build the `CNCTask` object. Bit confused... Right now, I've coded it out as ```IFormFile File = payload.File; CNCTask Task = payload.Task;``` but I don't think the API will really extract the body `form-data` properly with that... – JetsON Oct 04 '21 at 20:08
  • @The most classes are custom. How do you submit it ? using form and submit button or something else? Could you post your full view pls? – Serge Oct 04 '21 at 20:27
  • I'm not using a submit button, nor is there any view at all. This is just a Web API that will be used by a different service. I'm trying to send my POST requests right now, it works with just the `CNCTask` (as a `text` body) but I cannot get it to work with both an `IFormFile` and `CNCTask` (as a `form-data` body, so that I can include the file). My `CNCTask` object contains a JSON object of its own, that might be why my `form-data` request doesn't work... Any ideas ? – JetsON Oct 06 '21 at 19:32
  • I've added clear examples to my original post as an edit. – JetsON Oct 06 '21 at 19:36
  • @JetsON Thank you I updated my answer. This code was tested and is working properly – Serge Oct 06 '21 at 23:44
0

You can retrive form data as follows

var formdata = Request.Form["formdata"];
var model = JsonConvert.DeserializeObject<ModelEntity>(formdata);

And write your controller this way

public async Task<ActionResult<CNCTask>> Post(IFormFile file)
{
    var formdata = Request.Form["formdata"];
    var model = JsonConvert.DeserializeObject<InitialDemandEntity>(formdata);
            ...
}
decoder
  • 886
  • 22
  • 46