You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI Blazor调用ASP.NET MVC API切换语言失效求助

.NET MAUI Blazor调用ASP.NET MVC API切换语言Cookie不生效问题解决

问题场景

开发了两个应用:.NET MAUI Blazor移动应用,以及处理服务端逻辑的ASP.NET MVC API。API的LanguageController中实现了ChangeLanguageApi方法,可根据传入的culture参数设置语言Cookie并返回对应语言的响应消息。使用Swagger/Postman测试时能正常返回对应语言消息,但Blazor应用调用该接口时Cookie未生效,返回消息语言始终不变,Android模拟器和Windows端应用均存在此问题,需实现按传入culture显示对应语言消息。

相关代码

API端ChangeLanguageApi方法

[HttpPost]
public IActionResult ChangeLanguageApi([FromBody]string culture)
{
    if (culture == null || !_supportedLanguages.Contains(culture))
    {
        return StatusCode(StatusCodes.Status404NotFound,
            new Response { IsSuccess = false, Message = Common.SomethingWentWrong,  });
    }
    Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddMonths(6) });

    return StatusCode(StatusCodes.Status200OK,
            new Response { IsSuccess = true, Message = Common.Success,  });
}

API端Program.cs配置

builder.Services.Configure<LanguageSettings>(options => builder.Configuration.GetSection("LanguageSettings").Bind(options));
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
var mvcBuilder = builder.Services.AddControllersWithViews().AddDataAnnotationsLocalization(options =>
{
    var type = typeof(Resources.Common);
    var assembly = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
    var factory = builder.Services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
    var localizer = factory.Create("Common", assembly.Name);
    options.DataAnnotationLocalizerProvider = (t, f) => localizer;
});
var app = builder.Build();
var languageSettings = builder.Configuration.GetSection("LanguageSettings:SupportedLanguages").Get<List<string>>();
var supportedCultures = new List<CultureInfo>();
languageSettings.ForEach(x => supportedCultures.Add(new CultureInfo(x)));
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures
});

Blazor端切换语言代码

public async Task<Response> ChangeLanguage(string language)
{
    var returnResponse = new Response();
    using (var client = new HttpClient())
    {
        var url = $"{Settings.BaseUrl}{Apis.ChangeLanguage}";

        var serializedStr = JsonConvert.SerializeObject(language);

        var response = await client.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
        if (response.IsSuccessStatusCode)
        {
            string contentStr = await response.Content.ReadAsStringAsync();
            returnResponse = JsonConvert.DeserializeObject<Response>(contentStr);
        }
    }
    return returnResponse;
}

问题分析

  1. HttpClient无自动Cookie管理:Blazor中默认的HttpClient不会自动存储Cookie,也不会在后续请求中携带Cookie,而Swagger/Postman会自动处理Cookie生命周期,导致测试正常但Blazor调用无效。
  2. 当前请求未应用新语言:API设置Cookie后,当前请求的本地化上下文已初始化,返回的消息仍使用旧文化设置;同时因为Blazor未携带Cookie,后续请求也无法读取新的语言配置。
  3. 中间件顺序问题:若UseRequestLocalization中间件位置靠后,会导致请求未先处理本地化逻辑,Cookie无法生效。

解决方案

1. Blazor端手动管理Cookie

使用CookieContainer存储API返回的Cookie,并持久化到应用本地存储,后续请求携带该Cookie:

public async Task<Response> ChangeLanguage(string language)
{
    var returnResponse = new Response();
    var cookieContainer = new CookieContainer();
    using (var handler = new HttpClientHandler { CookieContainer = cookieContainer })
    using (var client = new HttpClient(handler))
    {
        var apiUri = new Uri($"{Settings.BaseUrl}{Apis.ChangeLanguage}");
        var serializedStr = JsonConvert.SerializeObject(language);

        var response = await client.PostAsync(apiUri, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
        
        // 持久化Cookie到MAUI Preferences
        var cookies = cookieContainer.GetCookies(apiUri);
        foreach (Cookie cookie in cookies)
        {
            Preferences.Set(cookie.Name, cookie.Value);
        }

        if (response.IsSuccessStatusCode)
        {
            string contentStr = await response.Content.ReadAsStringAsync();
            returnResponse = JsonConvert.DeserializeObject<Response>(contentStr);
        }
    }
    return returnResponse;
}

2. 全局HttpClient携带Cookie

注册全局HttpClient时自动添加存储的Cookie:

// 在MAUI Blazor的Program.cs中配置
builder.Services.AddScoped(sp =>
{
    var handler = new HttpClientHandler();
    var client = new HttpClient(handler)
    {
        BaseAddress = new Uri(Settings.BaseUrl)
    };

    // 读取本地存储的语言Cookie并添加到请求
    var langCookie = Preferences.Get(CookieRequestCultureProvider.DefaultCookieName, string.Empty);
    if (!string.IsNullOrEmpty(langCookie))
    {
        handler.CookieContainer.Add(new Uri(Settings.BaseUrl),
            new Cookie(CookieRequestCultureProvider.DefaultCookieName, langCookie));
    }

    return client;
});

3. 让API立即返回对应语言消息

在ChangeLanguageApi中手动设置当前线程文化,确保本次响应直接使用新语言:

[HttpPost]
public IActionResult ChangeLanguageApi([FromBody]string culture)
{
    if (culture == null || !_supportedLanguages.Contains(culture))
    {
        return StatusCode(StatusCodes.Status404NotFound,
            new Response { IsSuccess = false, Message = Common.SomethingWentWrong });
    }
    
    // 手动切换当前线程文化
    var targetCulture = new CultureInfo(culture);
    Thread.CurrentThread.CurrentCulture = targetCulture;
    Thread.CurrentThread.CurrentUICulture = targetCulture;

    Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddMonths(6), HttpOnly = false }); // 允许客户端读取

    return StatusCode(StatusCodes.Status200OK,
            new Response { IsSuccess = true, Message = Common.Success });
}

4. 调整API中间件顺序

确保UseRequestLocalization在路由、授权中间件之前执行:

var app = builder.Build();

// 先处理本地化
var languageSettings = builder.Configuration.GetSection("LanguageSettings:SupportedLanguages").Get<List<string>>();
var supportedCultures = new List<CultureInfo>();
languageSettings.ForEach(x => supportedCultures.Add(new CultureInfo(x)));
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures
});

// 再执行其他中间件
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();

内容的提问来源于stack exchange,提问作者Wosełko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:39:50