ASP.NET Core:将表单式语言切换改为列表式并实现Cookie持久化
问题背景
已有CultureController通过POST请求设置语言Cookie并返回原页面,但原下拉表单式语言选择需改为列表式;直接在URL追加?culture=en仅能临时切换当前页面语言,无法持久化Cookie,跳转后语言会恢复默认。
解决方案
方案1:JS+隐藏表单(推荐,简洁美观)
保留单个隐藏表单,通过JavaScript动态设置语言参数并提交POST请求,确保Cookie被持久化:
@using Microsoft.AspNetCore.Localization @using Microsoft.Extensions.Options @inject IOptions<RequestLocalizationOptions> LocalizationOptions @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}"; } <div class="language-toggle"> <a href="#" class="toggle-btn"><i class="fas fa-language"></i></a> <ul class="language-menu"> @foreach (var item in LocalizationOptions.Value.SupportedUICultures) { <li> <a href="javascript:void(0);" class="language-link @(requestCulture.RequestCulture.UICulture.Name == item.Name ? "active" : "")" data-culture="@item.Name"> @item.Name.ToUpper() </a> </li> } </ul> </div> <!-- 隐藏的语言提交表单 --> <form id="cultureForm" asp-controller="Culture" asp-action="SetCulture" asp-route-returnUrl="@returnUrl" method="post"> <input type="hidden" name="culture" id="cultureInput" /> </form> <script> // 绑定语言切换点击事件 document.querySelectorAll('.language-link').forEach(link => { link.addEventListener('click', function() { const culture = this.getAttribute('data-culture'); document.getElementById('cultureInput').value = culture; document.getElementById('cultureForm').submit(); }); }); // 切换菜单显示/隐藏 document.querySelector('.toggle-btn').addEventListener('click', function(e) { e.preventDefault(); document.querySelector('.language-menu').classList.toggle('show'); }); </script>
说明:
- 点击列表项时,JS将选中的语言值填入隐藏表单,提交到
CultureController的SetCulture方法,确保Cookie被设置。 returnUrl保留用户当前页面的路径及查询参数,提交后跳转回原页面。- 可通过CSS给
active类添加样式,标记当前选中的语言。
方案2:独立表单(无JS,兼容性好)
为每个语言项创建独立的POST表单,通过CSS将按钮伪装成链接样式,无需JavaScript即可实现功能:
@using Microsoft.AspNetCore.Localization @using Microsoft.Extensions.Options @inject IOptions<RequestLocalizationOptions> LocalizationOptions @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}"; } <div class="language-toggle"> <a href="#" class="toggle-btn"><i class="fas fa-language"></i></a> <ul class="language-menu"> @foreach (var item in LocalizationOptions.Value.SupportedUICultures) { <li> <form asp-controller="Culture" asp-action="SetCulture" asp-route-returnUrl="@returnUrl" method="post" class="language-form"> <input type="hidden" name="culture" value="@item.Name" /> <button type="submit" class="language-btn @(requestCulture.RequestCulture.UICulture.Name == item.Name ? "active" : "")"> @item.Name.ToUpper() </button> </form> </li> } </ul> </div> <!-- CSS 美化按钮,模拟链接样式 --> <style> .language-form { margin: 0; padding: 0; } .language-btn { background: transparent; border: none; padding: 0.5rem 1rem; color: inherit; cursor: pointer; text-align: left; width: 100%; text-decoration: none; } .language-btn:hover { text-decoration: underline; } .language-btn.active { font-weight: bold; } .language-menu { list-style: none; padding-left: 0; } </style>
说明:
- 每个语言项对应一个独立表单,点击按钮直接提交POST请求到控制器,自动设置Cookie并返回原页面。
- 通过CSS去除按钮默认样式,使其外观与链接一致,适合禁用JavaScript的场景。
关键注意事项
- 必须使用POST请求提交到
CultureController,确保Cookie被正确持久化(GET请求虽可临时切换语言,但无法触发控制器的Cookie设置逻辑)。 returnUrl已包含当前页面的路径和查询参数,确保切换后用户停留在原页面。
内容的提问来源于stack exchange,提问作者Carlo
相关产品推荐
相关产品推荐

