获取IPageRouteModelConvention版本信息

4

我之前问过一个问题如何添加本地化的URL, 其中IPageRouteModelConvention发挥了完美的作用。

有了它,我可以使用不同语言/名称的路由。


如果我使用 www.domain.com/nyheter(瑞典语)或www.domain.com/sistenytt(挪威语),我仍然只发现在 RouteData 中,使用了 News 路由(RouteData.Values["page"])。

我该如何获取哪个版本?

我知道我可以检查/解析 context.Request.Path,但想知道是否有一个内置的属性可以直接给我它。


startup 中。
services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddRazorPagesOptions(options =>
    {
        options.Conventions.Add(new LocalizedPageRouteModelConvention(new LocalizationService(appsettings.Routes)));
    });

appsettings.Routesappsettings.json中读取。

"Routes": [
  {
    "Page": "/Pages/News.cshtml",
    "Versions": [ "nyheter", "sistenytt" ]
  },
  and so on....
]

这个类

public class LocalizedPageRouteModelConvention : IPageRouteModelConvention
    {
        private ILocalizationService _localizationService;

        public LocalizedPageRouteModelConvention(ILocalizationService localizationService)
        {
            _localizationService = localizationService;
        }

        public void Apply(PageRouteModel model)
        {
            var route = _localizationService.LocalRoutes().FirstOrDefault(p => p.Page == model.RelativePath);
            if (route != null)
            {
                foreach (var option in route.Versions)
                {
                    model.Selectors.Add(new SelectorModel()
                    {
                        AttributeRouteModel = new AttributeRouteModel
                        {
                            Template = option
                        }
                    });
                }
            }
        }
    }
1个回答

2
要检索RouteData值,您可以在路由模板中指定令牌。例如,路由{version}将添加一个RouteDataversion,该值将从URL的第一个段中获取。在您的示例中,您未为version指定令牌,因此不会有RouteData值,正如您所描述的那样。
解决您特定问题的方法分为两部分:
1.创建新的SelectorModel时,使用上述方式中的令牌,而不是使用具体值。
2.使用这种方法后,您现在将能够从RouteData访问version值,但新问题是,任何值都可以提供,无论是否在配置中指定。
要解决第二个问题,您可以使用IActionConstraint。以下是一个实现:
public class VersionConstraint : IActionConstraint
{
    private readonly IEnumerable<string> allowedValues;

    public VersionConstraint(IEnumerable<string> allowedValues)
    {
        this.allowedValues = allowedValues;
    }

    public int Order => 0;

    public bool Accept(ActionConstraintContext ctx)
    {
        if (!ctx.RouteContext.RouteData.Values.TryGetValue("version", out var routeVersion))
            return false;

        return allowedValues.Contains((string)routeVersion);
    }
}

最初的回答:

VersionConstraint 接受一个允许值列表 (例如 nyheter, sistenytt),并检查 versionRouteData 值是否匹配。如果不匹配,则 "action"(实际上此时是一个页面)将不匹配,并最终出现 404。

有了这个实现,您可以更新 LocalizedPageRouteModelConventionApply 实现,使其看起来像这样:

var route = _localizationService.LocalRoutes().FirstOrDefault(p => p.Page == model.RelativePath);
if (route != null)
{
    model.Selectors.Add(new SelectorModel
    {
        AttributeRouteModel = new AttributeRouteModel
        {
            Template = "{version}"
        },
        ActionConstraints =
        {
            new VersionConstraint(route.Versions)
        }
    });
}

这个实现添加了一个新的SelectorModel,它使用一个Version RouteData值进行设置,并且只允许在配置中指定的值。"Original Answer"翻译成"最初的回答"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接