[英]How can I use DateOnly/TimeOnly query parameters in ASP.NET Core 6?
As of .NET 6 in ASP.NET API,如果你想獲取DateOnly
(或TimeOnly
)作為查詢參數,你需要單獨指定它的所有字段,而不是僅僅提供一個字符串(“2021-09-14”,或“10:54” :53" 用於TimeOnly
)就像DateTime
一樣。
如果它們是正文的一部分,我可以通過添加自定義 JSON 轉換器( AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(...))
)來解決這個問題,但它不適用於查詢參數。
我知道這可以用 model 活頁夾修復,但我不想為每個包含DateOnly/TimeOnly
的 model 創建一個 model 活頁夾。 有沒有辦法廣泛修復此應用程序?
演示:
讓我們假設你有一個 followwing 動作:
[HttpGet] public void Foo([FromQuery] DateOnly date, [FromQuery] TimeOnly time, [FromQuery] DateTime dateTime)
以下是它在 Swagger 中的表示方式:
我希望它表示為三個字符串字段:一個用於DateOnly
,一個用於TimeOnly
,一個用於DateTime
(這個已經存在)。
PS:不是Swagger的問題,是ASP.NET的一個。 如果我嘗試手動傳遞?date=2021-09-14
2021-09-14,ASP.NET 將無法理解。
事實證明,有兩種解決方案:
我去了TypeConverter
,一切正常! 由於 .Net 團隊不打算在 .Net 6 中添加對DateOnly/TimeOnly
完全支持,我決定創建一個 NuGet 來這樣做:
https://www.nuget.org/packages/DateOnlyTimeOnly.AspNet (源代碼)
將其添加到項目並按照描述配置Program.cs
,問題描述中描述的操作的 Swagger 將如下所示:
首先,您需要聲明從string
到DateOnly
類型轉換器(以及從string
到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);
}
}
( DateOnly
一個是相同的,但DateOnly
替換為TimeOnly
)
需要在DateOnly
和TimeOnly
上添加TypeConverterAttribute
。 可以這樣做:
TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
TypeDescriptor.AddAttributes(typeof(TimeOnly), new TypeConverterAttribute(typeof(TimeOnlyTypeConverter)));
為了使它更簡潔,可以將這段代碼包裝在擴展方法中:
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;
}
}
用法:
builder.Services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
我也在我身邊遇到了你的問題,似乎構造函數本身不支持無參數模式。 如以下代碼:
public DateOnly(int year, int month, int day)
{
throw null;
}
[NullableContext(1)]
public DateOnly(int year, int month, int day, Calendar calendar)
{
throw null;
}
雖然 DateTime 支持:
public DateTime Date
{
get
{
throw null;
}
}
因此,恐怕在對DateOnly
和TimeOnly
進行一些更新之前,我們都需要改用string
並將字符串划分為年、月和日,然后new DateOnly(int year, int month, int day)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.