Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change default format for DateTime parsing in ASP.NET Core

I get a Date in an ASP.NET Core Controller like this:

public class MyController:Controller{     public IActionResult Test(DateTime date) {      } } 

The framework is able to parse the date, but only in English format. When I pass 04.12.2017 as date parameter, I mean the 4th of december 2017. This would get parsed as english date, so my date object gets the value 12th of April 2017. I tried adding german only using this article and also this, but without success.

What needs to be done that ASP.NET Core automatically parse dates in the correct German format?

Update I Tried to set the RequestLocalizationOptions

services.Configure<RequestLocalizationOptions>(opts => {     var supportedCultures = new[]     {         new CultureInfo("de-DE"),     };      opts.DefaultRequestCulture = new RequestCulture("de-DE");     // Formatting numbers, dates, etc.     opts.SupportedCultures = supportedCultures;     // UI strings that we have localized.     opts.SupportedUICultures = supportedCultures; }); 

Still not working. I call example.com/Test?date=12.04.2017 and got this in my debugger:

public IActionResult Test(DateTime date) {     string dateString = date.ToString("d"); // 04.12.2016     string currentDateString = DateTime.Now.ToString("d"); // 14.01.2016     return Ok(); } 
like image 272
Lion Avatar asked Jan 13 '17 20:01

Lion


People also ask

How do I change the default DateTime format in C#?

var ci = new CultureInfo("en-US"); ci. DateTimeFormat. ShortDatePattern = "MM/dd/yyyy"; app.

How can check date format is correct or not in C#?

Use the DateTime. TryParseExact method in C# for Date Format validation. They method converts the specified string representation of a date and time to its DateTime equivalent. It checks whether the entered date format is correct or not.

What is TT time format?

Terrestrial Time (TT) is a modern astronomical time standard defined by the International Astronomical Union, primarily for time-measurements of astronomical observations made from the surface of Earth.


1 Answers

Had the same problem. While passing DateTime in request body works fine (because Json converter handles this staff), passing DateTime in query string as a parameter has some culture issues.

I did not like the "change all requests culture" approach, bacause this could have impact on other type's parsing, which is not desirable.

So my choise was to override the default DateTime model binding using IModelBinder: https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding

What I did:

1) Define custom binder (c# 7 syntax for 'out' parameter is used):

public class DateTimeModelBinder : IModelBinder {     public Task BindModelAsync(ModelBindingContext bindingContext)     {         if (bindingContext == null)             throw new ArgumentNullException(nameof(bindingContext));          // Try to fetch the value of the argument by name         var modelName = bindingContext.ModelName;         var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);         if (valueProviderResult == ValueProviderResult.None)             return Task.CompletedTask;          bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);          var dateStr = valueProviderResult.FirstValue;         // Here you define your custom parsing logic, i.e. using "de-DE" culture         if (!DateTime.TryParse(dateStr, new CultureInfo("de-DE"), DateTimeStyles.None, out DateTime date))         {             bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "DateTime should be in format 'dd.MM.yyyy HH:mm:ss'");             return Task.CompletedTask;         }          bindingContext.Result = ModelBindingResult.Success(date);         return Task.CompletedTask;     } } 

2) Define provider for your binder:

 public class DateTimeModelBinderProvider : IModelBinderProvider {     public IModelBinder GetBinder(ModelBinderProviderContext context)     {         if (context == null)         {             throw new ArgumentNullException(nameof(context));         }          if (context.Metadata.ModelType == typeof(DateTime) ||              context.Metadata.ModelType == typeof(DateTime?))         {             return new DateTimeModelBinder();         }          return null;     } } 

3) And finally, register your provider to be used by ASP.NET Core:

services.AddMvc(options => {     options.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider()); }); 

Now your DateTime will be parsed as expected.

like image 178
Igor Fedchenko Avatar answered Sep 23 '22 20:09

Igor Fedchenko