25

I have an Asp.Net Core application with MVC. I'm submitting a form with a date on the form.

Form looks (roughly) like this:

@model EditCustomerViewModel
<form asp-action="Edit">
    <input asp-for="ServiceStartDate" class="form-control" type="date" />
    <input type="submit" value="Update" class="btn btn-success" />
</form>

Controller action is:

[HttpPost]
public async Task<IActionResult> Edit(EditCustomerViewModel viewModel)
{
    // do stuff
    return RedirectToAction("Index");
}

View model is:

public class EditCustomerViewModel
{
    public Guid Id { get; set; }

    [DataType(DataType.Date)]
    public DateTime ServiceStartDate { get; set; }

    [DataType(DataType.Date)]
    public DateTime? ServiceEndDate { get; set; }

    // etc.
}

I'm in the UK, so dates are not in US format: dd/MM/YYYY. So by default I'm submitting 6/22/2017.

When looking on the submitted view model in controller during debugging, dates are null if submitted in UK format, but are fine if using US format. i.e. 6/22/2017 gives me null, but 22/6/2017 is bound to the correct date.

I have tried adding this to Startup.cs but it did not make any difference:

var supportedCultures = new[] { new CultureInfo("en-GB") };
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en-GB"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures
});
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-GB");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-GB");
CultureInfo.CurrentCulture = new CultureInfo("en-GB");
CultureInfo.CurrentUICulture = new CultureInfo("en-GB");

I've checked HTTP headers and I'm posting correct header:

Accept-Language: en-GB,en

What am I doing wrong? How can I tell MVC Core binders to bind dates in UK format?

p.s. I'm on VS2017 with *.csproj project file, with target framework .NetCoreApp 1.1

7
  • Have you already come across these two github.com/aspnet/Localization/issues/136, jerriepelser.com/blog/… Commented Jun 22, 2017 at 2:23
  • Also yyyy/MM/dd always work. if all else fails. Commented Jun 22, 2017 at 2:25
  • @Nkosi all the dance with CurrentCulture and CurrentUiCulture does not seem to make any difference on dates binding. I might go down the path of the second format you mention Commented Jun 22, 2017 at 13:26
  • @Nkosi yeah, got it sorted - I got myself confused first, but after unpeeling all the layers it worked. Commented Jun 22, 2017 at 13:36
  • 1
    "dates are null if submitted in UK format, but are fine if using US format. i.e. 6/22/2017 gives me null, but 22/6/2017 is bound to the correct date" - I'm guessing that you got the part after "i.e." mixed up. Commented Mar 13, 2018 at 10:37

3 Answers 3

27

A couple of things. I'm not sure you can push a new settings object into the middleware like that (You probably can), but most of the time I have seen it used in the ConfigureServices method like so :

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RequestLocalizationOptions>(options =>
    {
        options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en-NZ");
        options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("en-NZ") };
    });

    services.AddMvc();
}

Second. The order of your middleware is very important. Ensure that your call to UseRequestLocalization happens before UseMvc. Infact it should probably be the first thing in your pipeline unless there is a specific reason it can't be.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseRequestLocalization();
    app.UseMvc();
}

And finally, can you try removing all the providers from the pipeline (One of which is a cookie provider. I can't fathom why you would have this cookie but let's just try).

In your configure method call clear on the RequestCultureProviders list. This should ensure that there is nothing else there to set a culture.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RequestLocalizationOptions>(options =>
    {
        options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en-GB");
        options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en-GB") };
        options.RequestCultureProviders.Clear();
    });

    services.AddMvc();
}

More info : http://dotnetcoretutorials.com/2017/06/22/request-culture-asp-net-core/

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for looking into this. I've tried your suggestions, read through the article. Indeed my registration initially was in the wrong place. I've moved it above all MVC related registrations and it did not change a thing. These cultures don't seem to affect the way MVC binds the dates on requests.
Aaahhh... and it is working. Got a bit confused with the dates - once cleared all the surrounding stuff out of the way - I got the dates bound correclty.
I am using Net Core with Nginx on Debian. When I start directly on command line using dotnet app.dll the date works fine on POST, but when I start the application as a systemd service, the format changes. This answer worked for me just fine, with CultureInfo("pt-BR").
This works for me, I'm using net6, got confused when DateTime value from BodyRequest always converted to dd/MM/yyyy HH.mm.ss , but format that I need is en-GB format => HH:mm:ss
23

Updated answer for aspnet core 2.0

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        var supportedCultures = new[] { new CultureInfo("es-CO") };
        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("es-CO"),
            SupportedCultures = supportedCultures,
            SupportedUICultures = supportedCultures
        });

        // other configurations after (not before)
    }

1 Comment

This worked for me ASP.NET Core 3.1. Thanks! It's a pity that the DataFormatString that is specified in DisplayFormat in the model object is not respected with ApplyFormatInEditMode=true when binding.
3

Just in case anyone else comes across this question as I did, with an issue specifically around when the date is supplied in a HTTP Get query string.

If you supply the dates in a query string, culture configurations in the startup are ignored, even when specified as the only accepted.

The ASP.NET Core route value provider and query string value provider: Treat values as invariant culture. Expect that URLs are culture-invariant. In contrast, values coming from form data undergo a culture-sensitive conversion. This is by design so that URLs are shareable across locales.

You can see a workaround in the Microsoft docs here:

https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#globalization-behavior-of-model-binding-route-data-and-query-strings-1

1 Comment

The link points to a great bit of documentation that is very hard to find. Thanks for increasing its visibility.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.