Steven
Steven

Reputation: 18859

Bad Request (400) when posting IFormFile

I have a .NET Core API project that has a simple endpoint to upload a file:

[Route("api/[controller]")]
[ApiController]
public class FilesController : Controller
{
    private IFilesService _filesService { get; set; }

    public FilesController(IFilesService filesService)
    {
        _filesService = filesService;
    }

    [HttpPost]
    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        var model = await _filesService.UploadFile(file);
        return Ok();
    }
}

I've tried to test this using Postman, but each time I post a file to the endpoint, I get a 400 Bad Request error. My endpoint never gets hit.

I have several other POST endpoints that work just fine, so it's an issue either with this specific endpoint or with Postman. Here is my setup in Postman:

enter image description here

I've been spinning my wheels trying to figure out what the issue is, but there's not much to this at all, and I'm following examples I've seen online.

What am I doing wrong?

Upvotes: 4

Views: 4584

Answers (5)

Honza P.
Honza P.

Reputation: 1242

In my case I need to remove [ValidateAntiForgeryToken] from controller method

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> MyMethod([FromForm] IFormFile file)

became

[HttpPost]
public async Task<IActionResult> MyMethod([FromForm] IFormFile file)

Then I started to be able to call the method without getting HTTP400 error.

Upvotes: 0

Rickard von Haugwitz
Rickard von Haugwitz

Reputation: 11

I had this same problem trying to post a FormFile via AJAX rather than Form.Submit, but was unable to find the complete solution anywhere online. I'll post my solution here in case someone else stumbles upon this.

My problem was the [AutoValidateAntiForgeryToken] attribute on the controller, like Cole W mentioned in his comment. This does not seem to be the same issue Steven was facing originally, but apparently @Html.AntiForgeryToken() will create a hidden form field __RequestVerificationToken with the token, so that it gets posted on submit. However, when you try to manually post the form, this is not done, and you have to add this field yourself. For me, the client code ended up looking like this:

        const formData = new FormData();
        formData.append('file', file);
        formData.append(
            '__RequestVerificationToken',
            $('input[name=__RequestVerificationToken]').val());

        $.ajax({
            cache: false,
            type: 'POST',
            url: 'somePostUrl',
            data: formData,
            contentType: false,
            processData: false
        });

Postman would be equivalent with an extra key/value pair, although one would need to find a way to get the actual token. For testing purposes, if one does not have the option to simply remove the [AutoValidateAntiForgeryToken] attribute because it's in a base class, one can instead add [IgnoreAntiforgeryToken] to the current controller or endpoint method.

Hope this spares someone some headache in the future! I wasted quite some time on this...

Upvotes: 1

Chris.ZA
Chris.ZA

Reputation: 1286

I see you have set the [ApiController] attribute so I'm assuming that you are running ASP.Net Core 2.1.

If it's not set already, try modifying services.AddMvc() to services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); in Startup.cs.

I had a similar issue a while back and the above change fixed it for me. I found the answer to my problem here.

Hope this helps!

Upvotes: 5

Khushali jasoliya
Khushali jasoliya

Reputation: 370

try this.

[HttpPost]
    public async Task<IActionResult> UploadFile([FromForm]IFormFile file)
    {
        var model = await _filesService.UploadFile(file);
        return Ok();
    }

And remove ApiController attribute

Upvotes: 2

Sonal Borkar
Sonal Borkar

Reputation: 561

try below url in Postman client

  http://localhost:5001/api/Files/UploadFile

Upvotes: -1

Related Questions