Turns out, there are two solutions:
I went with TypeConverter
, and everything worked! Since .Net team are not planning to add full support for DateOnly/TimeOnly
in .Net 6, I've decided to create a NuGet to do so:
https://www.nuget.org/packages/DateOnlyTimeOnly.AspNet (source code)
After adding it to the project and configuring Program.cs
as described, Swagger for the action described in the question's description will look like this:
How does it work
First you need to declare type convertor from string
to DateOnly
(and one from string
to 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);
}
}
(one for DateOnly
is the same, but DateOnly
is replaced with TimeOnly
)
Than TypeConverterAttribute
needs to be added on DateOnly
and TimeOnly
. It can be done like this:
TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));
TypeDescriptor.AddAttributes(typeof(TimeOnly), new TypeConverterAttribute(typeof(TimeOnlyTypeConverter)));
To make it a bit cleaner this code can be wrapped in extension method:
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;
}
}
Usage:
builder.Services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
DateOnly
andTimeOnly
be represented by a single string argument (likeDateTime
currently is). So, there should be three fields on the screenshot above. Updated the question description. – Abiosis