如何在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
相关产品推荐
相关产品推荐

