【问题标题】:Get version when using IPageRouteModelConvention使用 IPageRouteModelConvention 时获取版本
【发布时间】:2019-09-29 03:10:57
【问题描述】:

我前段时间问how to add some kind of localized url'sIPageRouteModelConvention 是否以一种对我来说完美的方式发挥作用。

这样我就可以拥有不同语言/名称的路线。


如果我使用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.Routes 是从appsettings.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
                        }
                    });
                }
            }
        }
    }

【问题讨论】:

    标签: c# asp.net-core razor-pages asp.net-core-2.2


    【解决方案1】:

    要检索RouteData 值,您可以在模板中为路由指定一个标记。例如,路由{version} 将添加一个RouteDataversion,该值将取自URL 的第一段。在您的示例中,您没有为 version 指定令牌,因此正如您所描述的那样,它不会有 RouteData 值。

    针对您的具体问题的解决方案分为两部分:

    1. 在创建新的SelectorModels 时不要使用特定值,而是使用如上所述的令牌。
    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 获取允许值列表(例如nyhetersistenytt)并检查version RouteData 值是否匹配。如果不匹配,“动作”(此时它实际上是一个页面)将不匹配,最终会出现 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 值,并且被限制为仅允许配置中指定的值。

    【讨论】:

      猜你喜欢
      • 2017-04-28
      • 2023-04-01
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多