15
votes

Api method is looks like below

    [HttpPost]
    public async Task<BaseListResponse<MediaStorageModel>> MediaBrand(IFormFile file, int brandId)
    {
        var files = new List<IFormFile>();
        files.Add(file);

        var response = await this.Upload(files, "brand", brandId);

        return response;
    }

My postman configuration enter image description here

Upgrade my dotnet core from 2.0 to 2.1 thie become not working, can anyone help about this. What going wrong

11
Is your controller decorated with the [ApiController] attribute? That attribute, among other things, switches the default binding source from FromForm to FromBody, so if you need to actually accept multipart/form-data or x-www-urleconded request bodies, you need to add [FromForm] to the param.Chris Pratt
Even when adding FromForm attribute to the model parameter, I still get a null value for my IFileInfo, while I can see the file in the Request.Form.Files list...Vilmir
None of them worked for me. I just tried [FromForm(Name = "")] IFormFile file attribute and it worked for me.Mohammad Taherian

11 Answers

23
votes

I've faced the same issue, I was able to fix it by applying the 'Name' named parameter to FromForm attribute with name of the File field in the form. It specifies which field in the form to bind to the method parameter. Change your method signature as shown here.

[HttpPost("status")]
public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromForm(Name ="file")] IFormFile file, int brandId)
14
votes

Make sure the form is the correct enctype

<form asp-action="Edit" enctype="multipart/form-data">

I also had to change how the Model bind works from the generated code:

public async Task<IActionResult> Edit([Bind("Text,Example")] Example example)

to this code:

public async Task<IActionResult> Edit(Example example)
7
votes

In your form use

enctype="multipart/form-data"

5
votes

Adding (Name = "body") to the from form worked for me

Server Call:

[HttpPost]
  [Route("UploadImage")]

public IActionResult UploadImage([FromForm(Name = "body")]IFormFile formData)

Client code:

let formData = new FormData();
formData.append('body', event.target.files[0]);

const config = {
  headers: {
  'content-type': 'multipart/form-data',
  },
}

axios.post(ApiURL,formData, config);
1
votes

In my case it works as follows in net core

Controller:

[HttpPost]
public IActionResult ReadFormFile([FromForm]IFormFile miCsv)
{


}

Request body: Use as key the same name as the parameter

enter image description here

Request Header: Use as Content-Type: multipart/form-data; boundary=xxxxxxxxxxx the boundary can be any value

enter image description here

0
votes

Change your method argument to take below model and add [FromForm], it should work.

public class FileUploadViewModel
{
    public IFormFile File { get; set; }
    public int BrandId { get; set; }
}

public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromForm] FileUploadViewModel viewModel)
0
votes

The below code should work

[HttpPost]
public async Task<BaseListResponse<MediaStorageModel>> MediaBrand([FromQuery] int brandId, IFormFile file)
{
    var files = new List<IFormFile>();
    files.Add(file);

    var response = await this.Upload(files, "brand", brandId);

    return response;
}
0
votes

I have found a workaround to make it work:

Use HttpPut instead of HttPost on the controller action.

I was also surprised by this behavior. If someone can explain why it fixes the issue, it would help me.

0
votes

Update [FromForm] attribute, and don't put parameter into Headers, and put name of key is file and brandId.

I tested, It is Ok Add [FromForm] attribute

Only form-data and key is correct

0
votes

If you use javascript and FormData object you need set the name of each file to 'files'

this.files.forEach((f) => {
         formData.append("files", f, `${this.path}/${f.name}`);
      }); 

if you use other name in your post you need to set it in the attribute of the post method

formData.append("someName", f, `${this.path}/${f.name}`);

 public async Task<IActionResult> Post([FromForm(Name ="someName")] List<IFormFile> files)

Dont forget to set content-type

'Content-Type': 'multipart/form-data'
0
votes

In my case, i had an angular 6 app using a custom HttpInterceptor which adds content-type of "application/json" to every Http request along with a token before sending to an api. Something like below. Remove the line with 'Content-Type': application/json. Without that none of the solution here works. .Net Core is smarter now to translate whatever object u are sending to the api so far it matches the model u create for the object in angular.

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
  constructor() {}
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = localStorage.getItem('token');
      let clone: HttpRequest<any>;
      if (token) {
        clone = request.clone({
          setHeaders: {
            Accept: `application/json`,
            'Content-Type': `application/json`,
            Authorization: `Bearer ${token}`
          }
        });