Мак*_*вой 33 c# typeconverter model-binding asp.net-core-webapi .net-6.0
从 ASP.NET API 中的 .NET 6 开始,如果要获取DateOnly(或TimeOnly) 作为查询参数,则需要单独指定其所有字段,而不是仅提供字符串(“2021-09-14”或“10: 54:53" 为TimeOnly) 就像你可以为 一样DateTime。
如果它们是正文的一部分,我可以通过添加自定义 JSON 转换器 ( AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(...))) 来解决这个问题,但它不适用于查询参数。
我知道这可以通过模型绑定器修复,但我不想为每个包含DateOnly/TimeOnly. 有没有办法广泛修复这个应用程序?
演示:
假设您有以下操作:
[HttpGet] public void Foo([FromQuery] DateOnly date, [FromQuery] TimeOnly time, [FromQuery] DateTime dateTime)
下面是它在 Swagger 中的表示方式:
我希望它表示为三个字符串字段:一个 for DateOnly、一个 forTimeOnly和一个 for DateTime(这个已经存在)。
PS:这不是 Swagger 问题,而是 ASP.NET 问题。如果我尝试?date=2021-09-14手动传递,ASP.NET 将无法理解它。
Мак*_*вой 46
事实证明,有两种解决方案:
我和 一起去了TypeConverter,一切正常!由于 .Net 团队不打算DateOnly/TimeOnly在 .Net 6 中添加完全支持,因此我决定创建一个 NuGet 来执行此操作:
https://www.nuget.org/packages/DateOnlyTimeOnly.AspNet(源代码)
将其添加到项目并Program.cs按照描述进行配置后,问题描述中描述的操作的 Swagger 将如下所示:
首先,您需要声明类型转换器 from stringto DateOnly(以及一个 from stringto TimeOnly):
using System.ComponentModel;
using System.Globalization;
namespace DateOnlyTimeOnly.AspNet.Converters;
public class DateOnlyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
if (value is string str)
{
return DateOnly.Parse(str);
}
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
return 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("O");
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
Run Code Online (Sandbox Code Playgroud)
(其中一个 forDateOnly是相同的,但DateOnly被替换为TimeOnly)
需要TypeConverterAttribute添加DateOnly和TimeOnly。可以这样做:
TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
TypeDescriptor.AddAttributes(typeof(TimeOnly), new TypeConverterAttribute(typeof(TimeOnlyTypeConverter)));
Run Code Online (Sandbox Code Playgroud)
为了使其更简洁,可以将这段代码包装在扩展方法中:
using DateOnlyTimeOnly.AspNet.Converters;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
namespace Microsoft.Extensions.DependencyInjection;
public static class MvcOptionsExtensions
{
public static MvcOptions UseDateOnlyTimeOnlyStringConverters(this MvcOptions options)
{
TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
TypeDescriptor.AddAttributes(typeof(TimeOnly), new TypeConverterAttribute(typeof(TimeOnlyTypeConverter)));
return options;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
builder.Services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18001 次 |
| 最近记录: |