.net - MVC .net 站点的 URL 中具有语言属性的自定义路由
问题描述
我有一个需要本地化为多种不同语言的网站。为了实现这一点,我按照这里的教程 https://www.ryadel.com/en/setup-a-multi-language-website-using-asp-net-mvc/ 在我的路线配置中我有:
routes.MapRoute(
name: "DefaultLocalized",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" }, // en or en-US
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
目前我的语言切换器是这样工作的,对于每种可用的语言,我都会使用当前的 URL 并使用适当的语言 slug ie等en-US
创建一个链接ru-RU
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
@foreach (CultureViewModel culture in Global.EnabledCultures)
{
<li><span class="Language dropdown-item" title="@culture.DisplayName">@Html.Raw(Url.LangSwitcher(culture.DisplayName, ViewContext.RouteData, culture.Name))</span></li>
}
</div>
其中 Url.LangSwitcher 是 UrlHelper 的扩展
public static string LangSwitcher(this UrlHelper url, string name, RouteData routeData, string lang, bool isMainMenu = false)
{
var action = (routeData.Values["action"] ?? "").ToString().ToLower();
var controller = (routeData.Values["controller"] ?? "").ToString().ToLower();
var requestContext = HttpContext.Current.Request.RequestContext;
string link = "";
// We need to create a unique URL for the current page for each of the enabled languages for this portal
// If the lang variable is specified for current URL we need to substitute with the incoming lang variable
//we need to duplicate the RouteData object and use the duplicate for URL creation as
//changing the value of lang in RouteData object passed to this function changes the current culture of the request
RouteData localValues = new RouteData();
foreach (KeyValuePair<string, object> var in routeData.Values)
{
if (var.Key != "lang")
{
localValues.Values.Add(var.Key, var.Value);
}
}
localValues.Values.Add("lang", lang);
link = "<a href = \"" + new UrlHelper(requestContext).Action(action, controller, localValues.Values) + "\" >";
string img = "<img src=\"/Content/images/Flags/" + lang + ".gif\" alt = \"" + lang + "\"> " + name;
string closeTags = "</a>";
return link + img + closeTags;
}
所以它使用当前 URL 并切换语言 slug 并为我们正在创建的菜单输出一个链接。
这一切都适用于遵循标准{lang}/{controller}/{action}/{id}
模式的链接
但是,我希望能够在控制器上创建具有属性的自定义链接,如下所示:
[Route("brokers/this/is/a/custom/url")]
public ActionResult CompareBrokers(int page = 1)
{
所以当我尝试从这样的视图访问这条路线时:
@Url.Action("CompareBrokers", "Brokers")
生成的 URL 是这样的:
https://localhost:44342/brokers/this/is/a/custom/url?lang=en-US
我希望它是这样的
https://localhost:44342/en-US/brokers/this/is/a/custom/url
鉴于我目前的设置,关于如何实现我想要的任何建议?
UPDATE
将[Route("{lang}/brokers/this/is/a/custom/url")]
我的属性设置为有限的成功,只要当前 URL 中有一个 lang 变量,它就会起作用,所以如果我在http://site.url/en-US上,那么链接会正确创建,但是如果我在http://site.url他们没有。
我尝试在我的控制器中放置 2 个属性:
[Route("brokers/this/is/a/custom/url")]
[Route("{lang}/brokers/this/is/a/custom/url")]
但它只使用第一个
更新 2
按照评论中的建议,我使用了该属性:
[Route("{lang=en-GB}/brokers/this/is/a/custom/url")]
它工作得很好,我的链接可以正确生成,但是我需要能够适应默认本地化而不需要 URL 中的 lang var
解决方案
如果将两个属性与 order 参数一起放置,路由将首先尝试将第一个路由与 lang 参数匹配,如果未提供 lang 参数,它将回退到第二个路由。
[Route("{lang}/brokers/this/is/a/custom/url", Order = 1)]
[Route("brokers/this/is/a/custom/url", Order = 2)]
public ActionResult CompareBrokers(int page = 1)
{
}
更新:要在 lang 是默认语言时使用第二条路线,您可以通过添加 actionFilter 或 controllerActivator 从 routedata 中删除 lang:
if (filterContext.RouteData.Values["lang"]?.ToString() == _DefaultLanguage)
{
filterContext.RouteData.Values.Remove("lang");
}
推荐阅读
- c# - 如何将文本框的内容包装在滚动查看器中,以便在 WPF 中满时滚动?
- python - OpenCV perspectiveTransform - 将变换矩阵应用于 2D 坐标
- powershell - 如何将 Get-ADOrganizationalUnit 与 Get-ADUser 结合使用
- optimization - 多点交叉
- machine-learning - MultinomialNB 或 GaussianNB 或 CategoricalNB 在这里用什么?
- html - Bootstrap 4 导航栏示例在我的计算机上无法正常工作
- arrays - 给定 n,生成所有大小小于 0.5n 的排列
- cakephp - CakePHP ORM 查找具有多个包含(hasMany 关系)条件的查询
- couchdb - couchDB上的连接被拒绝
- python - 如何正确获取nba投篮图数据?