I'm new to web development generally but I'm creating a file repository that uses minimal APIs. I need to store customer files in silos so need to pass a TenantID in to choose the storage location. It all works fine in the Swagger UI - albeit with a choose file button - and returns a unique file id.
but I need to invoke it from a C# client and struggling to resolve how. The retrieve function works with httpclient but that just returns return Results.File(StoreLocation,MimeType) and I read it from Response.Content, no other data.
I've seen various items that say you can't do this in minimal API until .Net8 but how does Swagger manage it?

- 43
- 6
-
So if I understand correctly you have a minimal API endpoint which you can send file to and you want to do this programmatically (via HttpClient)? Am I understanding correctly? – Guru Stron Aug 03 '23 at 19:49
-
Yes, that's right, or any other valid client that can be coded into c# .NET framework. – MisterA Aug 07 '23 at 08:56
-
Please share the code for the endpoint. – Guru Stron Aug 07 '23 at 09:02
-
I don't have any valid code for the endpoint because I don't know how to code it. In the API it's App.MapPost("/Files", storeFile); and then I have a storeFile Function which does a lookup on an integer and uses a file path to store the file – MisterA Aug 07 '23 at 09:11
-
If you don't have a valid code for endpoint how are you going to call it? `App.MapPost("/Files", storeFile);` - that is the endpoint, what is the `storeFile`, please share it's code? – Guru Stron Aug 07 '23 at 09:15
-
The storeFile function is declared as ``private static async Task
storeFile(IFormFile formFile, int TenantID)`` – MisterA Aug 07 '23 at 09:17 -
Sorry it's Monday. The endpoint code is too long to post here basically ``var theTenant = await tData.GetTenantRecord(TenantID);`` to get a store location then ``using var stream = File.OpenWrite(storeFileName);`` ``await formFile.CopyToAsync(stream);`` it works fine using Swagger, I enter the ID, choose the file and it saves the file in the correct server filestore – MisterA Aug 07 '23 at 09:26
-
And that should have been App.MapPost("/Files/{TenantId}", storeFile); – MisterA Aug 07 '23 at 09:33
1 Answers
I solved this by first removing the TenantID parameter from storeFile. Using HttpClient I found the post content had to be MultipartFormDataContent with the content added as ByteContent and the name parameter set to "formFile" to match the storeFile parameter name
string filePath = txtUploadFileName.Text;
string fileName = Path.GetFileName(filePath);
Uri webService = new Uri($"{baseURL}/File");
var formContent = new MultipartFormDataContent();
formContent.Headers.ContentType.MediaType = "multipart/form-data";
var fileContent = File.ReadAllBytes(filePath);
formContent.Add(new ByteArrayContent(fileContent), "formFile", fileName);
var client = new HttpClient();
var response = await client.PostAsync(webService, formContent);
then I added the TenantId parameter back and tried various things such as adding string content as well but none worked. Then I noticed that in the working Swagger call the TenantId was simply appended to the URL instead of e.g. /File/Post?TenantId=2
it was /File/2
so I changed the URL to include the TenantId
Uri webService = new Uri($"{baseURL}/File/{txtUploadTenantID.Text.Trim()}");
and it works but I don't know what's going on in terms of URLs and the minimal API function mapping and I don't know how this would pan out with more than one parameter, but I hope this helps someone.

- 43
- 6