【问题标题】:Get subdomain in MVC for internationalization在 MVC 中获取子域以进行国际化
【发布时间】:2015-12-04 21:15:44
【问题描述】:

我正在开发一个包含多个翻译的 MVC 站点。我们希望通过 http://en.domain.comhttp://fr.domain.com 等子域来实现这一目标。我们还希望支持常规域http://domain.com

如果您手动更改子域,则翻译工作正常,但我正在寻找一种方法来自动执行此操作并维护整个当前 URL,以允许找到 http://en.domain.com/product 的用户单击链接并获取另一个语言版本同一页的。将子域(如果存在)隔离,将其从当前 url 中剥离,并替换为指定的语言版本似乎很简单。

本质上:

http://en.domain.com/product(原创)

http://domain.com/product(已清理)

http://fr.domain.com/producthttp://de.domain.com/product 等...(输出)

我开始寻找像 Request.Url.Subdomain 这样的内置功能,但得出的结论是没有这样的神奇生物。然后我继续进行基本的字符串操作,但它似乎真的很令人困惑,所以我开始寻找一个正则表达式的解决方案。

我已经使用一些通常为我工作的在线正则表达式测试器测试了这个正则表达式,并且他们在子域存在时正确识别它,但在代码实际运行时找不到结果。

我只使用了一点正则表达式,我希望这里有一些非常明显的地方我做错了。如果有更好的解决方案,我愿意接受其他方面的建议。

C#

string url = Request.Url.AbsoluteUri; //http://en.domain.com/
Regex regex = new Regex(@"/(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/", RegexOptions.IgnoreCase);
GroupCollection results = regex.Match(url).Groups;
Group result = results[0];

这是我目前的解决方案。没有我想要的那么优雅,但是对于一些消耗太多时间的东西,它现在可以按预期工作了。

查看

<a href="@Html.Action("ChangeLanguage", new { lang = "en" })">English</a>
<a href="@Html.Action("ChangeLanguage", new { lang = "fr" })">French</a>

动作

    public string ChangeLanguage(string controller, string lang)
    {
        string url = Request.Url.AbsoluteUri;

        Regex regex = new Regex(@"(?:https*://)?.*?\.(?=[^/]*\..{2,5})", RegexOptions.IgnoreCase);
        GroupCollection results = regex.Match(url).Groups;
        Group result = results[0];
        if (result.Success)
        {
            string[] resultParts = result.Value.Split('/');
            string newSubDomain = resultParts[0] + "//" + lang + ".";
            url = url.Replace(result.Value, newSubDomain);
        }
        else
        {
            string[] urlParts = url.Split('/');
            string oldParts = urlParts[0] + "//";
            string newParts = urlParts[0] + "//" + lang + ".";
            url = url.Replace(oldParts, newParts);
        }


        return url;
    }

【问题讨论】:

  • 显而易见的事情:C# 中不需要正则表达式分隔符。试试@"(?:https*://)?.*?\.(?=[^/]*\..{2,5})
  • 您是否考虑过使用子域以外的东西? http://domain.com/fr/product 也同样有效,并且不需要将每个新的“翻译”都注册为 DNS 条目。
  • @stribizhev 就是这样。我不是 100% 确定为什么中间部分有效,但似乎来自测试。
  • 我们过去使用过domain.com/en/etc...,它带来了另一组复杂性,因此我们想探索一些其他选择。
  • @Locke125:DVK 的回答对你有用吗?它看起来更干净。

标签: c# regex asp.net-mvc


【解决方案1】:

您可以使用自定义路由使其变得简单

routes.Add("LanguageRoute", new DomainRoute( 
"{language}.example.com/{controller}/{action}", // Domain with parameters 
"{controller}/{action}/{id}",    // URL with parameters 
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults 

))

并获取控制器上的语言值

  public ActionResult Index(string language)
    {
        return View();
    }

一个有用的链接可能对您有所帮助:http://benjii.me/2015/02/subdomain-routing-in-asp-net-mvc/

【讨论】:

  • 这是我想使用的解决方案类型,但我不太了解链接中 RouteBase 覆盖的用法,因为我可以看到它正在运行并更新路由,但是它发生在动作运行后,因此动作参数始终为空。我假设它与仍有待实现的 GetVirtualPath 方法有关,但还没有弄清楚。
  • 嘿 Locke 我刚刚对代码进行了采样作为基本用法。我需要睡觉,但明天我会给你一个编辑的工作示例。希望它对你有用。
  • 当然,这超出了我的真正要求。与此同时,我会继续努力。
  • 更多信息。我正在使用 MVC 5 属性路由并且我得到的图片是混合这两个东西不是最好的主意。或许可以做到,但看起来实现起来可能很棘手。
  • 通常你可以在注册路由方法上映射属性路由后注册你的正常路由参数。但是我们需要实现 DomainRoute 类来在我的方法中注册子域。由于我没有混淆两种情况的工作示例,因此我现在无法帮助您。 (一个有点棘手的问题是:如何混合过滤和路由。我知道大多数结构良好的解决方案都使用两者来服务本地化。(例如 nopCommerce、Umbraco)
【解决方案2】:

使用类似以下的东西(伪代码 - 应该添加安全检查等):

Uri myHost = new Uri("https://en.mydomain.com");
string hostname = myHost.Host; // returns en.mydomain.com
string subdomain = string.split(".", hostname)[0]; // subdomain = "en"

这将获得主机名,然后您可以将其拆分为“。”到一个数组,并取第一个元素。

编辑:链接到 Uri.Host 上的 MSDN 文档

https://msdn.microsoft.com/en-us/library/system.uri.host(v=vs.110).aspx

【讨论】:

  • 这基本上是我最初尝试的,但我需要一个不需要输入“魔术字符串”域的解决方案。对于某个处于营销位置的人来说,发布带有印刷或法律材料的 URL 并为其“挑选”一个域是一件相当普遍的事情。这意味着我们通常别无选择,只能为同一个站点支持多个域。
  • 这根本不需要任何魔术字符串。示例中的 Uri 构造函数参数可以来自任何内容,包括请求属性、配置文件等。为了简洁起见,我只是在那里使用了文字。重要的部分是 Uri.Host 属性返回的域名没有其他“东西”,如果按照惯例,语言始终是第一位的,那么您可以拆分句点并获取第一个元素,或者搜索模式的数组。营销人员有惊人的能力破解任何代码,不管你怎么做。
【解决方案3】:

我们在我的一个项目上做了类似的事情,这就是我获取当前子域的方式:

string GetSubDomain(Uri url, string defaultValue)
{
    string subdomain = defaultValue;

    if (url.HostNameType == UriHostNameType.Dns)
    {
        string host = url.Host;
        if (host.Split('.').Length > 2)
        {
            int index = host.IndexOf(".");
            int lastIndex = host.LastIndexOf(".");
            subdomain = index.Equals(lastIndex) ? defaultValue : host.Substring(0, index);
        }
    }

    return subdomain;
}

你会这样使用它:

var subdomain = GetSubDomain(HttpContext.Current.Request.Url, "en");

这假设您只需要当前 URL 中的第一个子域,因此 http://fr.example.comhttp://fr.something.example.com 都会产生 fr,而 http://example.com 会产生 en(本例中的默认值) .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    相关资源
    最近更新 更多