简体   繁体   English

基于不同域的Razor页面路由

[英]Razor page routing based on different domains

I'm trying to setup a single ASP.NET Core Razor Web app localized for use on multi domains. 我正在尝试设置一个本地化用于多域的ASP.NET Core Razor Web应用程序。 I have the localization working, with one different language for each domain. 我有本地化工作,每个域使用一种不同的语言。 But right now I want to have the .com domain accepting a routing parameter, to make the URL path decide with language to show. 但是现在我希望.com域接受路由参数,以使URL路径决定使用要显示的语言。

Something like: 就像是:

  • www.mysite.pt - no custom routing - www.mysite.pt/PageA works, localized in Portuguese. www.mysite.pt - 没有自定义路由 - www.mysite.pt/PageA工作,本地化为葡萄牙语。
  • www.mysite.com - custom routing - www.mysite.com/us/PageA goes to PageA, localized in en-US. www.mysite.com - 自定义路由 - www.mysite.com/us/PageA转到PageA,本地化为en-US。 But www.mysite.com/PageA should return a 404, as for this domain every page needs the country parameter. 但是www.mysite.com/PageA应该返回404,因为这个域每个页面都需要country参数。

For MVC this could be achieved by using the MapRoute with a custom IRouteConstraint to filter by domain. 对于MVC,可以通过使用MapRoute和自定义IRouteConstraint按域过滤来实现。 However with Razor pages, I only see the option to go with the conventions and add a class derived from IPageRouteModelConvention. 但是对于Razor页面,我只看到了与约定一起使用的选项,并添加了一个派生自IPageRouteModelConvention的类。

But I don't see a way on the IPageRouteModelConvention methodology to use a IRouteConstraint. 但我没有看到使用IRouteConstraint的IPageRouteModelConvention方法。 Is there a way to do this? 有没有办法做到这一点?

Not exactly the best solution... but worked this out: 不完全是最好的解决方案......但是解决了这个问题:

On ConfigureServices added a custom convention that takes a country parameter only with two country codes US and CA: 在ConfigureServices上添加了一个自定义约定,该约定仅使用两个国家/地区代码US和CA获取国家/地区参数:

  options.Conventions.Add(new CountryTemplateRouteModelConvention());

wethe this class being: 这个班级是这样的:

public class CountryTemplateRouteModelConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {

        var selectorCount = model.Selectors.Count;
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            // selector.AttributeRouteModel.SuppressLinkGeneration = false;

            //we are not adding the selector, but replacing the existing one
            model.Selectors.Add(new SelectorModel
            {

                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = -1,

                    Template = AttributeRouteModel.CombineTemplates(@"{country:length(2):regex(^(us|ca)$)}", selector.AttributeRouteModel.Template),
                }
            });
        }
    }
}

Then, before the UseMvc on Configure, I used two types of Rewrite rules: 然后,在ConfigureM的UseMvc之前,我使用了两种类型的Rewrite规则:

var options = new RewriteOptions();
options.Add(new CountryBasedOnDomainRewriteRule(domains: GetDomainsWhereCountryComesFromDomain(Configuration)));
options.Add(new CountryBasedOnPathRewriteRule(domains: GetDomainsWhereCountryComesFromPath(Configuration)));
app.UseRewriter(options);

The methods GetDomainsWhereCountryComesFromDomain and GetDomainsWhereCountryComesFromPath just read from the appsettings the domains where I want to have a single language, and the domains where I want the language to be obtained from the URL path. 方法GetDomainsWhereCountryComesFromDomain和GetDomainsWhereCountryComesFromPath只是从appsettings中读取我想要使用单一语言的域,以及我希望从URL路径获取语言的域。

Now, the two IRule classes: 现在,两个IRule类:

public class CountryBasedOnPathRewriteRule : IRule
{
    private readonly string[] domains;

    public CountryBasedOnPathRewriteRule(string[] domains)
    {
        this.domains = domains;
    }

    public void ApplyRule(RewriteContext context)
    {
        string hostname = context.HttpContext.Request.Host.Host.ToLower();
        if (!domains.Contains(hostname)) return;

        //only traffic that has the country on the path is valid. examples:
        // www.mysite.com/ -> www.mysite.com/US/
        // www.mysite.com/Cart -> www.mysite.com/US/Cart

        var path = context.HttpContext.Request.Path.ToString().ToLower();

        /* let's exclude the error page, as method UseExceptionHandler doesn't accept the country parameter */
        if (path == "/" || path == "/error")
        {
            //redirect to language default

            var response = context.HttpContext.Response;
            response.StatusCode = (int)HttpStatusCode.Moved;
            response.Headers[HeaderNames.Location] = "/us/"; //default language/country
            context.Result = RuleResult.EndResponse;
        }

        string pathFirst = path.Split('/')?[1];

        if (pathFirst.Length != 2) /* US and CA country parameter is already enforced by the routing */
        {
            var response = context.HttpContext.Response;
            response.StatusCode = (int)HttpStatusCode.NotFound;
            context.Result = RuleResult.EndResponse;
        }
    }
}

public class CountryBasedOnDomainRewriteRule : IRule
{
    private readonly string[] domains;

    public CountryBasedOnDomainRewriteRule(string[] domains)
    {
        this.domains = domains;
    }

    public void ApplyRule(RewriteContext context)
    {
        string hostname = context.HttpContext.Request.Host.Host.ToLower();
        if (!domains.Contains(hostname)) return;

        var path = context.HttpContext.Request.Path.ToString().ToLower();

        string pathFirst = path.Split('/')?[1];

        if (pathFirst.Length == 2) //we are trying to use www.mysite.co.uk/us which is not allowed 
        {
            var response = context.HttpContext.Response;
            response.StatusCode = (int)HttpStatusCode.NotFound;
            context.Result = RuleResult.EndResponse;
        }
    }
}

And that's it. 就是这样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM