Custom Model Binding in ASP.NET Core Minimal APIs

August 29, 2022 by Anuraj

AspNetCore MinimalApi

This post is about how to use custom model binding in ASP.NET Core Minimal APIs. By default ASP.NET Core Minimal APIs don’t support the FromBody attribute. This will become a challenge when we try to upload files to Web API with Minimal APIs. Here is some code for implementing File Upload in Minimal Web API.

app.MapPost("/upload", (Photo photo) =>
{
    app.Logger.LogInformation($"File uploaded with size {photo.File?.Length}");
    
    return Results.Ok();
}).Accepts<Photo>("multipart/form-data");

And the photo class will look like this.

class Photo
{
    public IFormFile? File { get; set; }
}

The multipart/form-data parameter which help us to display the File upload control in the Open API / Swagger UI. Without the custom binding implementation, we will get a 415 Unsupported Media Type error.

415 Unsupported Media Type Error

To fix this issue, we need to implement custom binding. We can find the details about Minimal API custom binding in the documentation. ASP.NET Core offers two ways to implement custom binding. I am using the BindAsync() method. To do this, we need to implement a static BindAsync() method in the photo class. Here is the modified photo class.

class Photo
{
    public IFormFile? File { get; set; }
    public static ValueTask<Photo?> BindAsync(HttpContext context,
                                                   ParameterInfo parameter)
    {
        var file = context.Request.Form.Files["File"];
        return ValueTask.FromResult<Photo?>(new Photo
        {
            File = file
        });
    }
}

Now if we run the app again and upload a file, we will be able to see the size of the file is logged in the output window / console. Based on the comment from David Fowler - async method to read the form, we can re write the code like this.

class Photo
{
    public IFormFile? File { get; set; }
    public static async ValueTask<Photo?> BindAsync(HttpContext context,
                                                   ParameterInfo parameter)
    {
        var form = await context.Request.ReadFormAsync();
        var file = form.Files["file"];
        return new Photo
        {
            File = file
        };
    }
}

This way we can support custom binding in Minimal APIs. And the FromBody attribute is supported in .NET 7.

Happy Programming :)

Copyright © 2024 Anuraj. Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license. This is a personal blog. The opinions expressed here represent my own and not those of my employer. Powered by Jekyll. Hosted with ❤ by GitHub