ASP.NET Web Api ApiController自定义DateTime模型绑定失效问题
问题:ASP.NET Web API中全局DateTime转UTC的自定义模型绑定器未触发
我正在使用ASP.NET Web Api和ApiController创建API,需要将所有DateTime值转换为UTC时间。现有如下Product模型:
public class Product { public string Name { get; set; } public DateTime Created { get; set; } }
对应的控制器:
[ApiController] public class SomeController : ControllerBase { [HttpPost] [Route("api/products")] public async Task<ActionResult> Create(Product product) { //.... do smth return Ok(); } }
我希望介入模型类的DateTime属性绑定过程并将其转换为UTC,因此创建了自定义DateTime模型绑定器,并通过config.ModelBinderProviders.Insert(0, new MyDateTimeBinderProvider());全局注册,但绑定器从未被触发。绑定器代码如下:
public class DateTimeBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (string.IsNullOrEmpty(valueProviderResult.FirstValue)) { return null; } DateTime value; if (DateTime.TryParse(valueProviderResult.FirstValue, null, DateTimeStyles.AdjustToUniversal, out value)) { bindingContext.Result = ModelBindingResult.Success(value.ToUniversalTime()); } else { //add error } return Task.CompletedTask; } }
解决方案
1. 绑定器未触发的原因
标记了[ApiController]的控制器,默认会使用JSON格式化程序(System.Text.Json或Newtonsoft.Json)处理请求体的模型绑定,而非传统的IModelBinder机制。你创建的自定义模型绑定器仅针对表单数据、查询参数等场景生效,不会处理JSON格式的请求体,因此未被触发。
2. 正确实现方式
方案一:使用JSON转换器(推荐,处理JSON请求体)
针对JSON格式的请求,需要创建自定义JsonConverter来处理DateTime的转换:
基于System.Text.Json的实现
public class UtcDateTimeConverter : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (DateTime.TryParse(reader.GetString(), null, DateTimeStyles.AdjustToUniversal, out var dateTime)) { return dateTime.ToUniversalTime(); } // 可根据需求添加错误处理 return DateTime.MinValue; } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { // 输出UTC格式时间,带Z标识 writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")); } }
全局注册转换器:
// Program.cs 或 Startup.cs builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new UtcDateTimeConverter()); });
方案二:处理非JSON场景(表单、查询参数)
如果需要处理表单提交、URL查询参数中的DateTime,需确保IModelBinderProvider正确实现:
public class MyDateTimeBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { // 仅为DateTime类型提供绑定器 if (context.Metadata.ModelType == typeof(DateTime)) { return new DateTimeBinder(); } return null; } }
注册方式:
builder.Services.AddControllers(options => { options.ModelBinderProviders.Insert(0, new MyDateTimeBinderProvider()); });
3. 额外说明
如果只需确保接口返回的DateTime为UTC格式,使用Newtonsoft.Json时可直接配置:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; });
但要处理传入的DateTime转换为UTC,仍需使用自定义JSON转换器。
内容的提问来源于stack exchange,提问作者gophero
相关产品推荐
相关产品推荐

