21

I'm trying to send a image and text fields to an API endpoint but I'm received

Unsupported content type 'multipart/form-data; boundary=---------------------------81801171514357

This is a ASP.NET Core 2.1 Web API. I have this:

[HttpPost("/api/account"), Authorize]
public void SaveUser(UserModel info)

And my model:

    [JsonProperty(PropertyName = "avatar")]
    [DataType(DataType.Upload)]
    public IFormFile Avatar { get; set; }

    [JsonProperty(PropertyName = "name")]
    [DataType(DataType.Text)]
    public string Name { get; set; }

Then I use axios:

    var formData = new FormData();
    formData.append("avatar", imageFile);
    formData.append("name", name);
    axios.post("/api/account", formData);

I expected this method to run, not throw an exception. But how? I have tried to add:

[Consumes("application/json", "multipart/form-data")]

But no success.

Then I tried:

[HttpPost("/api/account"), Authorize]
public void SaveUser([FromForm]UserModel info)

The method runs, but the properties is empty on info object :(

UPDATE: Solution, don't use JsonProperty PropertyName. Use the variable name.

Vy Do
  • 46,709
  • 59
  • 215
  • 313
mrcode
  • 465
  • 2
  • 5
  • 16
  • 1
    You should use `public void SaveUser(IFormCollection collection)` when uploading a file with detail. Follow this https://stackoverflow.com/questions/53825794/webapi-is-it-possible-to-post-an-iformcollection-and-object-in-an-action – Khai Nguyen Jan 29 '19 at 05:30
  • Is there any demo to reproduce your issue? I made a test with your current code, it wokrs correctly. – Edward Jan 29 '19 at 06:40
  • I have another method: [HttpPost("/api/avatar"), Authorize] public void SaveAvatar(IFormFile avatar) There is no problem. But when i add IFormFile and properties in a model, then i get "Unsupported content type 'multipart/form-data". – mrcode Jan 29 '19 at 08:50
  • Now, i found that i cant use the JsonProperty name, i must use Avatar and Name (the property names). Then it works fine. Is that possible to set the name of the properties? – mrcode Jan 29 '19 at 12:01
  • This is the solution.[https://stackoverflow.com/questions/60275185/file-upload-in-api-in-dotnet-core-wpf-windows-app][1] – Rezaul Khan Mar 15 '20 at 07:43

3 Answers3

26

Maybe you should try decorate controller input and model with [FromForm] attribute? See more info here: web api parameters binding.

In given example your controller action should look like this:

[HttpPost("/api/account"), Authorize]
public void SaveUser([FromForm]UserModel info)

In model:

[FromForm(Name="avatar")]
public IFormFile Avatar { get; set; }

[FromForm(Name="name")]
public string Name { get; set; }
joostas
  • 485
  • 5
  • 10
  • Yes, i have try to add, [FromForm] then all the properties in my model is null. – mrcode Jan 29 '19 at 09:41
  • 1
    Try to add this attribute on model properties. – joostas Jan 29 '19 at 13:41
  • 1
    i found that i cant use the JsonProperty name, i must use Avatar and Name (the property names). Then it works fine. Is that possible to set the name of the properties? – mrcode Jan 29 '19 at 13:46
  • 2
    Use should use [FromForm] attribute in Controller action and in model definition. At least that worked to me. – joostas Jan 29 '19 at 19:54
  • 2
    This just saved my day! I was up all night with this issue. Thank you so much @joostas – Dean Friedland Mar 20 '20 at 13:31
  • @joostas: I have a list in my model with other types and it is working for everything except list type. I'm sending it by using JSON.Stringify from UI. Any idea why it is not working? – Ranger May 14 '20 at 01:21
2

1-send multi part file

            [HttpPost, Route("postimagenews")]
            public IActionResult PostImageNews([FromForm] IFormFile file)
            {
                try
                {
                    if (file == null || file.Length == 0)
                    {
                        return BadRequest("Please send a photo");
                    }
                    //create unique name for file
                    var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
    
                    //set file url
                    var savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/news", fileName);
    
                    using (var stream = new FileStream(savePath, FileMode.Create))
                    {
                        file.CopyTo(stream);
                    }
    
                    return Ok(fileName);
                }
                catch
                {
                    return BadRequest("error in upload image");
                }
            }

2-recive multi part file

            public static async Task<string> PostImage(string apiendpoint, IFormFile data)
            {
                using (var httpClient = new HttpClient())
                {
                    var multipartContent = new MultipartFormDataContent();
                    var fileContent = new ByteArrayContent(GetFileArray(data));
                    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
                    multipartContent.Add(fileContent, "file",data.FileName);
                    var resultUploadImage= await httpClient.PostAsync(apiendpoint, multipartContent);
                    if (resultUploadImage.IsSuccessStatusCode)
                    {
                        var fileName=(await resultUploadImage.Content.ReadAsStringAsync()).Replace("\"", "");
                        return fileName;
                    }
                    return "";
                }
            }
    
            public static byte[] GetFileArray(IFormFile file)
            {
                using (var ms = new MemoryStream())
                {
                    file.CopyTo(ms);
                    return ms.ToArray();
                }
            }

3-send file multi part with postman

enter image description here

Diako Hasani
  • 1,384
  • 13
  • 14
-3

Here is a working example for what you are looking for

Controller:

[HttpPost]
public async Task<IActionResult> SaveFile([FromForm] IFormFile file) {
  // Your code here
}

And inside your model:

public IFormFile File { get; set; }

Change async Task<IActionResult> if you don't need it...

Srdjan
  • 584
  • 3
  • 6