Receive file and other form data together in ASP.NET Core Web API (boundary based request parsing)

Solution 1:

I had the similar issue and I solved the problem by using [FromForm] attribute and FileUploadModelView in the function as follow:

[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload([FromForm] FileUploadViewModel model, [FromForm] string member_code)
{
    var file = model.File;
    
    // ...
}

Solution 2:

This is a quick solution for anyone who is facing the same issue:

You will use ajax to send the following formData

let formData: FormData;
formData = new FormData();
formData.append('imageFile', imageFile);
formData.append('name', name);

Then you will receive it in your controller like this:

public string Post(IFormCollection data, IFormFile imageFile)

Then you will access the data as you do normally:

var name = data["name"];

Solution 3:

In HomeController.cs

using Microsoft.AspNetCore.Hosting;
.......
private IHostingEnvironment _environment;

public HomeController(IHostingEnvironment environment)
{
    _environment = environment;
}

[HttpPost]
[ValidateAntiForgeryToken]        
public IActionResult Index(IFormCollection formdata)
{
 var files = HttpContext.Request.Form.Files;
 foreach (var file in files)
 {
     var uploads = Path.Combine(_environment.WebRootPath, "Images");
     if (file.Length > 0)
     {
        string FileName = Guid.NewGuid(); // Give file name
        using (var fileStream = new FileStream(Path.Combine(uploads, FileName), FileMode.Create))
        {
            file.CopyToAsync(fileStream);
        }       
     }
  }
}

In view - Index.cshtml

<form method="post" enctype="multipart/form-data" >
 .....
</form>

You can try this code.

Thanks!!

Solution 4:

I'm using the following code to accomplish this in order to parse a response from Mailgun, which comprises both files and text values.

Please note that "dashifying" is just so property names like "MessageHeaders" get turned into "message-headers"; obviously you should use whatever logic makes sense for your use case.

Controller:

using System;
using Microsoft.AspNetCore.Mvc;
using NuGet.Protocol.Core.v3;

namespace Potato
{
    [Route("api/[controller]")]
    public class MailgunController : Controller
    {
        [HttpPost]
        public IActionResult Post()
        {
            MailgunEmail email = new MailgunEmail(Request);

            return Ok(email.ToJson());
        }
    }
}

Model:

using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;

namespace Potato
{
    public class MailgunEmail
    {
        public IEnumerable<IFormFile> Attachments { get; set; }

        public string Recipient { get; set; }
        public string Sender { get; set; }
        public string From { get; set; }
        public string Subject { get; set; }
        public string BodyPlain { get; set; }
        public string StrippedText { get; set; }
        public string StrippedSignature { get; set; }
        public string BodyHtml { get; set; }
        public string StrippedHtml { get; set; }
        public int? AttachmentCount { get; set; }
        public int Timestamp { get; set; }
        public string Token { get; set; }
        public string Signature { get; set; }
        public string MessageHeaders { get; set; }
        public string ContentIdMap { get; set; }

        public MailgunEmail(HttpRequest request)
        {
            var form = request.Form;

            Attachments = new List<IFormFile>(form.Files);

            foreach (var prop in typeof(MailgunEmail).GetProperties()) {
                string propName = Dashify(prop.Name);
                var curVal = form[propName];
                if (curVal.Count > 0) {
                    prop.SetValue(this, To(curVal[0], prop.PropertyType), null);
                }
            }
        }

        private object To(IConvertible obj, Type t)
        {
            Type u = Nullable.GetUnderlyingType(t);

            if (u != null) {
                return (obj == null) ? GetDefaultValue(t) : Convert.ChangeType(obj, u);
            } else {
                return Convert.ChangeType(obj, t);
            }
        }

        private object GetDefaultValue(Type t)
        {
            if (t.GetTypeInfo().IsValueType) {
                return Activator.CreateInstance(t);
            }
            return null;
        }

        private string Dashify(string source)
        {
            string result = "";
            var chars = source.ToCharArray();
            for (int i = 0; i < chars.Length; ++i) {
                var c = chars[i];
                if (i > 0 && char.IsUpper(c)) {
                    result += '-';
                }
                result += char.ToLower(c);
            }
            return result;
        }
    }
}