.NET Core API List<IFormFile> files not received from .NET MVC MultipartFormDataContent POST

Viewed 1657

I have a .NET Core API POST method below:

    public IActionResult UploadFiles([FromForm(Name = "files")] List<IFormFile> files, [FromForm(Name = "providerName")] string providerName) 
    {
        try
        {
            return WriteToXlsx(files,providerName); //documents
        }
        catch (Exception ex)
        {

            return BadRequest($"Error: {ex.Message}");
        }
    }

It works fine when posting from Postman, files are received. However when trying to post from ASP.NET MVC as shown below, it appears the files are not being received. there is no error message, but the file count from List files is zero. The string "providerName" is being received.

    [HttpPost]
    public async Task<ActionResult> ContentTransformation(IEnumerable<HttpPostedFileBase> files, string providerName)
    {
      
        try
        {
            HttpClientHandler clientHandler = new HttpClientHandler();
            var httpClient = new HttpClient(clientHandler);
            var multipartFormDataContent = new MultipartFormDataContent();

            foreach (HttpPostedFileBase file in files)
            {
                byte[] fileData;
                using (var reader = new BinaryReader(file.InputStream))
                {
                    fileData = reader.ReadBytes(file.ContentLength);
                }
                var fileContent = new ByteArrayContent(fileData);
                multipartFormDataContent.Add(fileContent, "files");
            }

            StringContent sProviderName = new StringContent(providerName);
            multipartFormDataContent.Add(sProviderName, "\"providerName\"");

            var response = await httpClient.PostAsync(ConfigurationManager.AppSettings["ContentTransformationAPI"], multipartFormDataContent);

            FileContentResult metadataContent = new FileContentResult(response.Content.ReadAsByteArrayAsync().Result, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

            return File(
                fileContents: metadataContent.FileContents,
                contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                fileDownloadName: "metadata.xlsx"
                );
        }
        catch (Exception ex)
        {

            ViewBag.Message = "File upload failed!! " + ex.Message;
            ModelState.Clear();
            return View();
        }
    }
1 Answers

Edit

I've found the problem. You're discarding the FileName of the uploads, so it doesn't bind properly when you POST the data from your MVC controller to your API controller. All you need to change is:

multipartFormDataContent.Add(fileContent, "files");

to

multipartFormDataContent.Add(fileContent, "files", file.FileName);

and then the files will be bound properly.

Old answer

Your code (controller + form element) works for me, which makes me think it's your form you've not setup properly. At its simplest, it should look like this:

@using (Html.BeginForm(
    "ContentTransformation", 
    "YourControllerName", // Make sure you change this.
    FormMethod.Post, 
    new { enctype = "multipart/form-data" }))
{
    <input type="file" name="files" multiple="multiple" />
    <input type="submit" />
}

I think the part you might be missing is the new { enctype = "multipart/form-data" }. The multipart/form-data enctype is what allows input elements to upload file data, so your uploader won't work without it.

Related