ASP.NET Core 3.1 Dto类属性自定义ModelBinder未触发问题咨询
问题原因与解决方案
根本原因
你的控制器Action参数标注了[FromBody],ASP.NET Core中[FromBody]默认使用JSON序列化器(System.Text.Json或Newtonsoft.Json)直接反序列化请求体,不走常规的ModelBinder执行流程:
- 你编写的
SessionIdModelBinder、MyCustomModelBinderProvider仅对路由、查询字符串、表单数据等非请求体JSON的数据源生效 - JSON序列化器无法识别自定义
SessionId类型的反序列化规则,反序列化失败后整个dto参数被判定为null,触发ASP.NET Core 3.1默认的非空参数校验,就会返回The dto field is required.报错
解决方案
方案1:继续使用[FromBody]接收JSON请求,新增JSON类型转换器
这是最推荐的方案,符合JSON请求的处理逻辑。
若使用默认System.Text.Json序列化器
- 实现自定义JsonConverter
public class SessionIdJsonConverter : JsonConverter<SessionId> { public override SessionId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var value = reader.GetString(); var parseResult = SessionId.Parse(value); if (parseResult.IsFailure) { throw new JsonException(parseResult.Errors.First().Message); } return parseResult.Data; } public override void Write(Utf8JsonWriter writer, SessionId value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } }
- 全局注册转换器
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new SessionIdJsonConverter()); });
若使用Newtonsoft.Json序列化器
- 实现自定义JsonConverter
public class SessionIdNewtonsoftConverter : JsonConverter<SessionId> { public override void WriteJson(JsonWriter writer, SessionId value, JsonSerializer serializer) { writer.WriteValue(value.ToString()); } public override SessionId ReadJson(JsonReader reader, Type objectType, SessionId existingValue, bool hasExistingValue, JsonSerializer serializer) { var value = reader.Value?.ToString(); var parseResult = SessionId.Parse(value); if (parseResult.IsFailure) { throw new JsonSerializationException(parseResult.Errors.First().Message); } return parseResult.Data; } }
- 全局注册转换器
services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new SessionIdNewtonsoftConverter()); });
方案2:不使用[FromBody],沿用已有的ModelBinder逻辑
如果你的请求参数不是JSON格式,直接去掉Action参数上的[FromBody]特性,或者根据数据源替换为[FromForm]/[FromQuery],已注册的MyCustomModelBinderProvider就会自动生效,Dto属性上的[ModelBinder]特性也可以省略。
内容的提问来源于stack exchange,提问作者Saeed Ganji
相关产品推荐
相关产品推荐

