Leks
Leks

Reputation: 31

Use MVC's model binding from application code

As a sample of what I'm trying to accomplish, here in MapPost I'm manually parsing the body of the HTTP request.

// Program.cs

using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

Type[] types = new[] { typeof(SampleDto1), typeof(SampleDto2), <other unknown types> };

foreach (var type in types)
{
    app.MapPost(type.Name, async (HttpContext httpContext) =>
    {
        var request = await JsonSerializer.DeserializeAsync(
            httpContext.Request.Body,
            type,
            new JsonSerializerOptions(JsonSerializerDefaults.Web),
            httpContext.RequestAborted);

        return Results.Ok(request);
    });
}

app.Run();

internal record SampleDto1(string Input) { }
internal record SampleDto2(string Input) { }

This works, yay! However, ... ASP.NET Core's MVC has all these sophisticated ModelBinding functionality and I really would like to use that. Because that opens up possibilities for binding to querystring parameters and other sources instead of only the request body.

Basically I want to replace the call to JsonSerializer with a call to framework code.

I've been browsing the ASP.NET Core source code and at first the DefaultModelBindingContext looked promising. However, I soon stumbled on some internal classes which I couldn't access from my code.

Long story short, .. is it at all possible to plug-in to MVC's model binding from application code?


Update: Although it doesn't show from the initial question, the solution should work dynamically with any request type. Not only SampleDto1 and SampleDto2. That's why explicit parameter binding from Minimal API won't do the trick.

Upvotes: 0

Views: 302

Answers (1)

Ruikai Feng
Ruikai Feng

Reputation: 11824

You could try the codes :

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
builder.Services.AddSingleton<Service>();
app.MapPost("/{id}", ([FromRoute] int id,
                     [FromQuery(Name = "p")] int page,
                     [FromBody]SampleDto1 sample1,
                     [FromBody] SampleDto2 sample2,
                     [FromServices] Service service,
                     [FromHeader(Name = "Content-Type")] string contentType)
                     => { });
app.Run();

internal record SampleDto1(string Input) { }
internal record SampleDto2(string Input) { }

You could read the official document for more details: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0#explicit-parameter-binding

Upvotes: 1

Related Questions