You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:07:51