如何修改 Blazor(服务器)中的当前文化日期格式?

Iva*_*anH 11 c# asp.net-core blazor blazor-server-side asp.net-core-3.1

ASP.NET Core Blazor 全球化和本地化声明:

Blazor 的@bind功能根据用户的当前文化执行格式并解析值以进行显示。
可以从System.Globalization.CultureInfo.CurrentCulture property.

这个说法是对的,但问题是,文化必须在使用之前设置(或者可能每次刷新 DOM 时)。

为了演示,我将使用标准的 blazor 计数器应用程序。让我们修改Counter.razor

@page "/counter"
@using System.Globalization;

<h1>Counter</h1>
<input type="text" @bind="currentDate" />

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private DateTime currentDate = DateTime.Now;
    private int currentCount = 0;

    private void IncrementCount() {
        if (currentCount < 2) Utils.SetCCDateFormat();
        currentCount++;
    }

    public class Utils {
        public static void SetCCDateFormat() {
            var cc = CultureInfo.CurrentCulture.Clone() as CultureInfo;
            cc.DateTimeFormat.ShortDatePattern = "dd-yyyy-m";
            CultureInfo.CurrentCulture = cc;
            CultureInfo.CurrentUICulture = cc;
        }
    }

} 
Run Code Online (Sandbox Code Playgroud)

结果是:

  • 当页面首次呈现时,文本框包含按服务器默认文化格式化的日期。
  • 当第一次和第二次按下按钮时,日期格式是 dd-yyyy-m

我试图修改 中的日期OnAfterRenderOnInitialized但没有成功。我发现,唯一可用的解决方案是在剃刀标记的乞求上设置格式。

@{Utils.SetCCDateFormat();}
Run Code Online (Sandbox Code Playgroud)

有没有办法修改 CurrentCulture 以使其在 blazor 电路中持久化?

观察到的行为是正确的还是错误?

编辑

到目前为止我发现了什么

可以CultureInfo.CurrentCulture在创建 blazor 终结点之前在中间件中设置区域性属性 ( ),并且更改在电路生命周期内是持久的。当我们修改CurrentCulture组件生命周期方法时,更改只是暂时的(直到方法结束)。

我对问题的理解是

  • 创建电路后,它会将当前文化存储在某处
  • 服务器的线程数有限
  • 需要时将线程分配给电路,当前区域性由开头存储的内容设置
  • 可以修改CurrentCulture,但这不会影响设置存储,因此当调用另一个事件方法(其他线程)时,将使用原始区域性。

所以似乎问题是:如何在已经创建的电路文化设置中修改它?

也许这是不可能的,有必要进行完全刷新(再次通过导航启动请求)并使用中间件来设置修改后的区域性。文化储存存在只是我的猜想,我没有任何参考支持。

非常感谢 Tyeth 和 Ashquzzaman 的帮助,但我并没有将他们的尝试作为答案。

Ash*_*man 4

1)使用中间件

例子:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      //your Code
        app.Use(async (context, next) =>
        {
            var culture = CultureInfo.CurrentCulture.Clone() as CultureInfo;// Set user culture here
            culture.DateTimeFormat.ShortDatePattern = "dd-yyyy-m";
            CultureInfo.CurrentCulture = culture;
            CultureInfo.CurrentUICulture = culture;

            // Call the next delegate/middleware in the pipeline
            await next();
        });
      //your Code
    }
Run Code Online (Sandbox Code Playgroud)

2)带有服务的自定义中间件:

服务 :

public interface ICultureService
{
    void SetCCDateFormat();
}
public class CultureService : ICultureService
{
    public void SetCCDateFormat()
    {
        CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
        culture.DateTimeFormat.ShortDatePattern = "dd-yyyy-m";
        CultureInfo.CurrentCulture = culture;
        CultureInfo.CurrentUICulture = culture;
    }
}
Run Code Online (Sandbox Code Playgroud)

中间件:

public class CultureMiddleware
{
    private readonly RequestDelegate _next;

    public CultureMiddleware(RequestDelegate next)
    {
        _next = next;

    }

    public Task Invoke(HttpContext context, ICultureService culture)
    {           
        culture.SetCCDateFormat();
        return this._next(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

启动:

    public void ConfigureServices(IServiceCollection services)
    {
        //Your Code
        services.AddScoped<ICultureService, CultureService>();
        //Your Code
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //Your Code
        app.UseMiddleware<CultureMiddleware>();
        //Your Code
    }
Run Code Online (Sandbox Code Playgroud)

文化.剃刀:

@page "/culture"
@inject ICultureService CultureService
<h1>Counter</h1>
<input type="text" @bind="currentDate" />

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private DateTime currentDate = DateTime.Now;
    private int currentCount = 0;

    private void IncrementCount()
    {
         if (currentCount < 2) CultureService.SetCCDateFormat();
        currentCount++;
    }
}
Run Code Online (Sandbox Code Playgroud)

3)如果可以更改应用程序的默认文化,请使用本地化中间件。Blazor 服务器应用程序正在使用本地化中间件进行本地化和全球化。请求的当前文化是在本地化中间件中设置的。该方法中启用了本地化中间件Startup.Configure。必须在任何可能检查请求区域性的中间件之前配置本地化中间件(例如,app.UseMvcWithDefaultRoute())。

例子:

var culture = new CultureInfo("en-US");
            culture.DateTimeFormat.ShortDatePattern = "dd-yyyy-MM";
            var supportedCultures = new List<CultureInfo> { culture };
        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture(culture, culture),
            // Formatting numbers, dates, etc.
            SupportedCultures = supportedCultures,
            // UI strings that we have localized.
            SupportedUICultures = supportedCultures
        });
Run Code Online (Sandbox Code Playgroud)