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

如何在ASP.NET Core 6中使用DateOnly/TimeOnly类型的查询参数

全局适配ASP.NET 6查询参数DateOnly/TimeOnly绑定方案

实现原理

ASP.NET 对查询参数的绑定默认会优先使用TypeConverter进行类型转换,我们只要全局注册DateOnly和TimeOnly对应的自定义类型转换器,即可实现全局生效的字符串解析适配,无需为每个包含对应类型的模型单独实现绑定器。

步骤1:实现自定义类型转换器

首先分别实现DateOnly和TimeOnly的类型转换器:

using System.ComponentModel;
using System.Globalization;

public class DateOnlyTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
    {
        if (value is string dateStr && DateOnly.TryParse(dateStr, CultureInfo.InvariantCulture, out var date))
        {
            return date;
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
    {
        return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
    }

    public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is DateOnly date)
        {
            return date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

public class TimeOnlyTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
    {
        if (value is string timeStr && TimeOnly.TryParse(timeStr, CultureInfo.InvariantCulture, out var time))
        {
            return time;
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
    {
        return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
    }

    public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is TimeOnly time)
        {
            return time.ToString("HH:mm:ss", CultureInfo.InvariantCulture);
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

步骤2:全局注册类型转换器

在Program.cs的最开头添加以下代码,注册两个转换器:

TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
TypeDescriptor.AddAttributes(typeof(TimeOnly), new TypeConverterAttribute(typeof(TimeOnlyTypeConverter)));

// 后续保留你原有启动逻辑即可
var builder = WebApplication.CreateBuilder(args);
// ...其他服务注册

完成这两步后,你就可以直接通过?date=2021-09-14&time=10:54:53的形式传参,ASP.NET会自动完成解析绑定。

可选:Swagger适配

如果需要Swagger对应显示日期、时间格式的字符串输入框,而非拆分的字段,在注册Swagger服务时添加类型映射即可:

using Microsoft.OpenApi.Models;

builder.Services.AddSwaggerGen(options =>
{
    options.MapType<DateOnly>(() => new OpenApiSchema { Type = "string", Format = "date" });
    options.MapType<TimeOnly>(() => new OpenApiSchema { Type = "string", Format = "time" });
});

注意事项

  • 该方案对查询参数、路由参数都生效,和你原有针对请求体的JSON转换器配置互不冲突
  • 示例中使用了固定不变的区域格式(CultureInfo.InvariantCulture),如果需要适配多区域格式,可以自行调整解析逻辑

内容的提问来源于stack exchange,提问作者maxc137

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 17:09:02