如何在Asp.Net Core中设置日期绑定的文化?

23

我有一个使用Asp.Net Core MVC框架的应用程序。我正在提交一个带有日期的表单。

表单大致如下:

@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>

控制器动作是:

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

视图模型是:

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.
}

我在英国,因此日期格式不是美国格式:dd/MM/YYYY。因此,默认情况下我提交的日期是6/22/2017

在调试期间查看控制器中的提交视图模型时,如果以英国格式提交,则日期为空,但如果使用美国格式,则正常。即6/22/2017会给我null,但22/6/2017绑定到了正确的日期。

我尝试将以下内容添加到Startup.cs中,但没有任何变化:

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");

我已经检查了HTTP头,并发布了正确的头信息:

Accept-Language: en-GB,en

我做错了什么?如何告诉MVC Core绑定器绑定英国格式的日期?

p.s. 我正在使用带有*.csproj项目文件的VS2017,并且目标框架为.NetCoreApp 1.1


你是否已经遇到了这两个链接 https://github.com/aspnet/Localization/issues/136 和 http://www.jerriepelser.com/blog/how-aspnet5-determines-culture-info-for-localization/? - Nkosi
@Nkosi,使用“CurrentCulture”和“CurrentUiCulture”进行的所有操作似乎对日期绑定没有任何影响。我可能会选择你提到的第二种格式。 - trailmax
你能否添加你最终是如何通过自我回答使其工作的。我很感兴趣。 - Nkosi
@Nkosi 下面是我使用的答案。此外,我还必须调整应用程序的js端的文化 - 它增加了混乱。 - trailmax
1
日期如果以英国格式提交,则为空,但使用美国格式则正常。即6/22/2017会给我空值,但22/6/2017将绑定到正确的日期。- 我猜你把“即”后面的部分搞混了。 - Ergwun
显示剩余2条评论
3个回答

26

有几件事情。我不确定你是否可以像那样将新的配置对象推入中间件中(你可能可以),但大多数情况下我看到它是在 ConfigureServices 方法中使用的,如下所示:

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();
}

其次,中间件的顺序非常重要。确保在调用UseMvc之前调用UseRequestLocalization。事实上,它可能应该是你管道中的第一件事,除非有特定的原因不能这样做。

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

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

最后,您能否尝试从管道中删除所有提供程序(其中之一是Cookie提供程序。我无法想象您为什么会有此Cookie,但我们可以尝试一下)。

在您的Configure方法中,对RequestCultureProviders列表调用clear。这应该确保没有其他内容设置了区域设置。

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();
}

更多信息: http://dotnetcoretutorials.com/2017/06/22/request-culture-asp-net-core/


感谢您关注此事。我尝试了您的建议,并阅读了文章。实际上,我的注册最初放错了位置。我已将其移动到所有MVC相关注册之上,但并没有改变任何事情。这些文化似乎不会影响MVC绑定请求中的日期。 - trailmax
啊哈...它正在工作。我对日期有点困惑-一旦把周围的所有东西清除掉-我就正确地绑定了日期。 - trailmax
我正在Debian上使用Net Core和Nginx。当我直接在命令行上使用“dotnet app.dll”启动时,POST的日期正常工作,但是当我将应用程序作为systemd服务启动时,格式会发生变化。这个答案对我非常有效,使用了“CultureInfo(“pt-BR”)”。 - Pablo
这对我有用,我正在使用net6,当来自BodyRequest的DateTime值总是转换为dd/MM/yyyy HH.mm.ss时感到困惑,但我需要的格式是en-GB格式=>HH:mm:ss。 - Konsultan IT Bandung

22

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)
    }

2
这对我在ASP.NET Core 3.1中起作用了。谢谢!遗憾的是,当绑定时ApplyFormatInEditMode=true时,模型对象中DisplayFormat中指定的DataFormatString未被尊重。 - phn

2

如果您像我一样遇到了特定于HTTP Get查询字符串中提供日期的问题,那么请注意,如果您在查询字符串中提供日期,则启动时的区域配置将被忽略,即使指定为唯一接受的配置。

ASP.NET Core路由值提供程序和查询字符串值提供程序: 将值视为不变的文化。 期望URL是文化不变的。 相比之下,来自表单数据的值会进行文化敏感的转换。这是出于设计考虑,以便URL可以在各种语言环境下共享。

您可以在Microsoft文档中查看解决方法:

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


这个链接指向一份非常难以找到的优秀文档。感谢您提高了它的可见性。 - ajbeaven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接