Razor страницу маршрутизации на основе разных доменов - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь настроить одно веб-приложение ASP.NET Core Razor, локализованное для использования в нескольких доменах. У меня работает локализация, с одним языком для каждого домена. Но сейчас я хочу, чтобы домен .com принимал параметр маршрутизации, чтобы путь URL-адреса определялся с отображаемым языком.

Что-то вроде:

  • www.mysite.pt - нет пользовательской маршрутизации - www.mysite.pt/PageA работает, локализовано на португальском языке.
  • www.mysite.com - пользовательская маршрутизация - www.mysite.com/us/PageA переходит на страницу PageA, локализованную в en-US. Но www.mysite.com/PageA должен возвращать 404, поскольку для этого домена каждая страница нуждается в параметре страны.

Для MVC это может быть достигнуто с помощью MapRoute с пользовательским IRouteConstraint для фильтрации по домену. Однако на страницах Razor я вижу только возможность пойти с соглашениями и добавить класс, производный от IPageRouteModelConvention.

Но я не вижу способа в методологии IPageRouteModelConvention использовать IRouteConstraint. Есть ли способ сделать это?

1 Ответ

0 голосов
/ 20 июня 2019

Не совсем лучшее решение ... но сработало:

На ConfigureServices добавлено пользовательское соглашение, которое принимает параметр страны только с двумя кодами стран США и CA:

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

В этом классе:

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),
                }
            });
        }
    }
}

Затем, перед использованием UseMvc при настройке, я использовал два типа правил перезаписи:

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

Методы GetDomainsWhereCountryComesFromDomain и GetDomainsWhereCountryComesFromPath просто читают из наборов приложений домены, где я хочу иметь один язык, и домены, где я хочу получить язык по URL-пути.

Теперь два класса 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;
        }
    }
}

И это все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...