0

Datetimes with unspecified Kind are giving my endpoints some problems. So I want to apply a converter globally to make any unspecified kind datetimes to local. I was able to do this for all datetimes being read from json with JsonConverter<DateTime> but since url/query parameters aren't json they don't get the conversion. Is there a way to do this for url/query parameters as well before it hits the endpoint logic or do I need to do it in each endpoint?

Robert Petty
  • 197
  • 1
  • 3
  • 17
  • Are you using MVC? You can use a custom `ModelBinder` if so... See also [Parse QueryString into strongly typed object](https://stackoverflow.com/q/37703540/215552) and [Parse and modify a query string in .NET Core](https://stackoverflow.com/q/29992848/215552) – Heretic Monkey Feb 03 '21 at 18:53

1 Answers1

0

Your issue can be solved by custom model binding which is a kind of cross-cutting concerns. The idea of cross-cutting concerns is to find a common extensibility point in a pipeline to inject some code to do something without repeating or spreading the code everywhere. So here you can use a custom IModelBinder which should always works. However as recommended by Microsoft, in this case you have a string representation of DateTime, you need to convert that to DateTime. This should be done with TypeConverter instead which is even simpler than using a custom IModelBinder. You can create a custom TypeConverter for your DateTime string (obtained from the query string, route data, ...) to deal with some specific format of DateTime.

Here is just an example:

public class CustomDateTimeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return typeof(DateTime?).IsAssignableFrom(destinationType) || base.CanConvertTo(context, destinationType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        //your custom logic to parse a DateTime from your specific format here
        //For a simple and funny example, I use the word "today"
        if(value?.ToString() == "today")
        {
            return DateTime.Today;
        }
        return base.ConvertFrom(context, culture, value);
    }
}

Now you need to register this custom type converter for DateTime such as in the ConfigureServices method in Startup.cs (can be put in static methods as well):

TypeDescriptor.AddAttributes(typeof(DateTime), new TypeConverterAttribute(typeof(CustomDateTimeConverter)));

Now suppose your model property (of DateTime or DateTime?) name is Date, the following query string should send the DateTime.Today to your model property:

?date=today
King King
  • 61,710
  • 16
  • 105
  • 130