簡體   English   中英

如何在 ASP.NET Core 6 中使用 DateOnly/TimeOnly 查詢參數?

[英]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 將如下所示:

在此處輸入圖片說明

它是如何工作的

首先,您需要聲明從stringDateOnly類型轉換器(以及從stringTimeOnly類型轉換器):

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

需要在DateOnlyTimeOnly上添加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;
        }
    }

因此,恐怕在對DateOnlyTimeOnly進行一些更新之前,我們都需要改用string並將字符串划分為年、月和日,然后new DateOnly(int year, int month, int day)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM