我正在尝试设置一个本地化的ASP.NET Core Razor Web应用程序,以在多个域上使用。我正在进行本地化,每个域使用一种不同的语言。但是现在我想让.com域接受路由参数,以使URL路径决定要显示的语言。
类似的东西:
对于MVC,这可以通过将MapRoute与自定义IRouteConstraint结合使用以按域进行过滤来实现。 但是,对于Razor页面,我只能看到遵循约定并添加从IPageRouteModelConvention派生的类的选项。
但是我在IPageRouteModelConvention方法论上看不到使用IRouteConstraint的方法。 有办法吗?
答案 0 :(得分:0)
并不是最好的解决方案...但是可以解决:
在ConfigureServices上添加了一个自定义约定,该约定仅使用带有两个国家/地区代码US和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;
}
}
}
就是这样。