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?
- 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 Answers
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
- 61,710
- 16
- 105
- 130