CarterCommunity / Carter

Carter is framework that is a thin layer of extension methods and functionality over ASP.NET Core allowing code to be more explicit and most importantly more enjoyable.
MIT License
2.05k stars 172 forks source link

C# IFormFile Web Api PUT/POST wants application/json rather than multipart/form-data #357

Open johnwnowlin opened 2 weeks ago

johnwnowlin commented 2 weeks ago

Using C# 6, Carter 6.1.1 to create a PUT web api end point.

something like:

public void AddRoutes(IEndpointRouteBuilder app)
{
    app.MapPut("api/putLogo/{customerNumber}", PutLogo);
}
public async Task<IResult> Put(string customerNumber, IFormFile file) { 
 // get all the file information.
}

Unfortunately, swagger sees it as a "application/json" and therefore returns

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter "IFormFile file" from the request body as JSON. ---> System.Text.Json.JsonException: '0x89' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0. ---> System.Text.Json.JsonReaderException: '0x89' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.

PostMan oddly returns a 404. I have tried it without the customerNumber parm, annotated [FromForm], [FromBody] etc.

I can take the same code and move it to an ApiController and it works as expected.

using Microsoft.AspNetCore.Mvc;

using static RepData.Domain.IFSClient;

namespace RepData.Controllers;
[Route("api/[controller]")]
[ApiController]
public class LogoController : ControllerBase
{
    [HttpPut("{customerNumber}")]
    public async Task<IResult> Put(string customerNumber, IFormFile file)
    {

Not sure if I have something configured oddly or what, but it is what I am seeing.

jchannon commented 2 weeks ago

I’m not sure net6.0 minimal api supports file binding. You will have to use request.Form.Files or use the Carter extension methods called request.BindFile(s)

On Fri, 14 Jun 2024 at 18:50, John Nowlin @.***> wrote:

Using C# 6, Carter 6.1.1 to create a PUT web api end point.

something like:

public void AddRoutes(IEndpointRouteBuilder app){ app.MapPut("api/putLogo/{customerNumber}", PutLogo);}public async Task Put(string customerNumber, IFormFile file) { // get all the file information.}

Unfortunately, swagger sees it as a "application/json" and therefore returns

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter "IFormFile file" from the request body as JSON. ---> System.Text.Json.JsonException: '0x89' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0. ---> System.Text.Json.JsonReaderException: '0x89' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.

PostMan oddly returns a 404. I have tried it without the customerNumber parm, annotated [FromForm], [FromBody] etc.

I can take the same code and move it to an ApiController and it works as expected.

using Microsoft.AspNetCore.Mvc; using static RepData.Domain.IFSClient; namespace RepData.Controllers;[Route("api/[controller]")][ApiController]public class LogoController : ControllerBase{ [HttpPut("{customerNumber}")] public async Task Put(string customerNumber, IFormFile file) {

Not sure if I have something configured oddly or what, but it is what I am seeing.

— Reply to this email directly, view it on GitHub https://github.com/CarterCommunity/Carter/issues/357, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAZVJUIHUD5QIGHJGUVZWTZHMUO3AVCNFSM6AAAAABJKYNURKVHI2DSMVQWIX3LMV43ASLTON2WKOZSGM2TGOBSHA2DEOI . You are receiving this because you are subscribed to this thread.Message ID: @.***>