I'm trying to implement a single ModelBinder for all my DTOs:
public class MyModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext) {
var queryDto = bindingContext.ModelType.GetConstructors()[0].Invoke([]);
// fill properties via Reflection
bindingContext.Result = ModelBindingResult.Success(queryDto);
return Task.CompletedTask;
}
}
This is an example of DTO:
public class Dto {
public int Id { get; set; }
public string Name { get; set; }
}
Now, if I try to set an endpoint like this:
app.MapGet("/get-dto", ([FromQuery] [ModelBinder(typeof(MyModelBinder))] Dto dto) => {
return CalculateResultSomehow(dot);
});
The compiler gives me the error:
error ASP0020: Parameter 'dto' of type Dto should define a bool TryParse(string, IFormatProvider, out Dto) method, or implement IParsable
If I remove the [FromQuery] attribute, the lambda has a warning:
ModelBinderAttribute should not be specified for a MapGet Delegate parameter
And the code breaks at runtime with the Exception:
An unhandled exception occurred while processing the request. InvalidOperationException: Body was inferred but the method does not allow inferred body parameters... Did you mean to register the "Body (Inferred)" parameter(s) as a Service or apply the [FromServices] or [FromBody] attribute?
Now, since I'm implementing a parsing logic based on Reflection, I don't want to implement the static TryParse() on every single DTO of my application (I have 100 of them...). And I shouldn't: I already have the ModelBinder.
A controller's action works perfectly using the same system:
[ApiController]
public class MyController
{
[HttpGet("/get-dto")]
public Dto GetDto([FromQuery] [ModelBinder(typeof(MyModelBinder))] Dto dto) {
return dto;
}
}
I'm lost here. What am I missing? Why isn't this working for Minimal APIs?
[AsParameters]to bind complex model instead of nested model. For your requirement I am confused that why you bind the nested model from body or from form? I think from query will be limited with lengh by browser or web server, also it is not secure that sensitive information can be exposed.[FromQuery]reads the parameters from the query string.[AsParameters]does not work if my DTO has nested classes (for example: a PaginationDto has property Filters, which is a list of FilterDto, and every FilterDto has a PropertyName and a PropertyValue...)