我正在尝试为我的所有 DTO 实现一个
ModelBinder
:
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;
}
}
这是 DTO 的示例:
public class Dto {
public int Id { get; set; }
public string Name { get; set; }
}
现在,如果我尝试设置这样的端点:
app.MapGet("/get-dto", ([FromQuery] [ModelBinder(typeof(MyModelBinder))] Dto dto) => {
return CalculateResultSomehow(dot);
});
编译器给我错误:
错误 ASP0020:Dto 类型的参数“dto”应定义 bool TryParse(string, IFormatProvider, out Dto) 方法,或实现 IParsable
如果我删除 [FromQuery] 属性,则 lambda 会出现警告:
不应为 MapGet Delegate 参数指定 ModelBinderAttribute
代码在运行时因异常而中断:
处理请求时发生未处理的异常。 InvalidOperationException:推断了主体,但该方法不允许推断主体参数... 您是否打算将“Body(推断)”参数注册为服务或应用 [FromServices] 或 [FromBody] 属性?
现在,由于我正在实现基于反射的解析逻辑,因此我不想在应用程序的每个 DTO 上实现静态
TryParse()
(我有 100 个 DTO...)。我不应该:我已经有了 ModelBinder
。
使用相同的系统,控制器的动作可以完美地工作:
[ApiController]
public class MyController
{
[HttpGet("/get-dto")]
public Dto GetDto([FromQuery] [ModelBinder(typeof(MyModelBinder))] Dto dto) {
return dto;
}
}
我在这里迷路了。我缺少什么?为什么这不适用于最小 API?
我在这里迷路了。我缺少什么?为什么这不适用于最小 API?
因为Minimal API 不支持模型绑定器。模型绑定器是“完整”框架的一部分(可以从
ModelBinderAttribute
命名空间 - Microsoft.AspNetCore.Mvc
间接得出结论)
有关 Minimal API 支持的绑定,请参阅 Minimal API 应用程序中的参数绑定 文档。