共计 5120 个字符,预计需要花费 13 分钟才能阅读完成。
在使用 ASP.NET Core 中的 TemplateMatcher 解决 route template 匹配字符串问题时,遇到的一个新问题:匹配时忽略类型约束。我们将通过分析源代码和查找相关线索,提供一种解决方案来解决这个问题。
引言
在使用 ASP.NET Core 开发 Web 应用程序时,我们经常需要进行 URL 路由的匹配。ASP.NET Core 提供了 TemplateMatcher 类,它可以帮助我们实现 route template 与 URL 路径的匹配。然而,在使用 TemplateMatcher 解决一些基本的 route template 匹配问题后,我们发现了一个新的问题:当 route template 中包含类型约束(即 inline constraint)时,匹配过程会忽略这些类型约束。本文将介绍如何解决这个问题。
使用 TemplateMatcher 的实现代码如下:
var routeTemplate = TemplateParser.Parse(template);
var values = new RouteValueDictionary();
var matcher = new TemplateMatcher(routeTemplate, values);
if (matcher.TryMatch(path, values))
{return new KeyValuePair(template, values);
}
分析
我们首先需要了解 TemplateMatcher 是如何进行路由匹配的。在 TemplateMatcher 的实现代码中,我们可以看到它使用了 TemplateParser 来解析 route template,并将解析结果传递给 TemplateMatcher 进行匹配。然而,在 TemplateParser.Parse 方法返回的解析结果中,并没有提供对类型约束的支持。
解决方案
通过查看 ASP.NET Core 的源代码,我们发现在 IntRouteConstraintsTests.cs#L22 和 ConstraintsTestHelper.cs#L8 中有一些重要的线索,我们可以利用这些线索来解决这个问题。
首先,我们可以使用下面的代码将 TemplateParser.Parse 方法返回结果中的 InlineConstraints 打印出来:
var routeTemplate = "/{blogApp}/{postType}/{id:int
}/{**slug}";
var parsedTemplate = TemplateParser.Parse(routeTemplate);
var values = new RouteValueDictionary();
foreach (var parameter in parsedTemplate.Parameters)
{foreach (var inlineConstraint in parameter.InlineConstraints)
{Console.WriteLine(parameter.Name + ":" + inlineContraint.Constraint);
}
}
输出:
id:int
从输出结果中我们可以看到,InlineConstraints 中包含了类型约束的信息。接下来,我们需要创建一个 IRouteConstraint 的实例,并将解析出的类型约束传递给它。我们可以使用以下代码创建 IRouteConstraint 实例:
IServiceCollection services = new ServiceCollection();
services.AddOptions();
using ServiceProvider sp = services.BuildServiceProvider();
var routeOptions = sp.GetRequiredService>();
var constraintResolver = new DefaultInlineConstraintResolver(routeOptions, sp);
var routeConstraint = constraintResolver.ResolveConstraint(inlineContraint.Constraint);
Console.WriteLine(routeContraint);
输出:
Microsoft.AspNetCore.Routing.Constraints.IntRouteConstraint
通过以上代码,我们成功创建了一个 IntRouteConstraint 的实例。现在我们可以将这个实例用于匹配过程中。
接下来,我们可以使用以下代码演示如何使用 TemplateMatcher 进行 URL 路径的匹配,并考虑到类型约束:
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Template; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; var routeTemplates = new[] {"/{blogApp}/{postType}/{id:int
}/{**slug}", "/{blogApp}/{postType}/{idOrSlug}.html" }; var url = "https://www.toymoban.com/diary/problem/681.html"; var urlPath = new Uri(url).AbsolutePath; IServiceCollection services = new ServiceCollection(); services.AddOptions(); using ServiceProvider sp = services.BuildServiceProvider(); var routeOptions = sp.GetRequiredService >(); var constraintResolver = new DefaultInlineConstraintResolver(routeOptions, sp); foreach (string routeTemplate in routeTemplates) {Console.WriteLine("routeTemplate:" + routeTemplate); var parsedTemplate = TemplateParser.Parse(routeTemplate); var values = new RouteValueDictionary(); var matcher = new TemplateMatcher(parsedTemplate, values); if (matcher.TryMatch(urlPath, values)) {Console.WriteLine("TemplateMatcher matched: true"); foreach (var item in values) {Console.WriteLine("{0}: {1}", item.Key, item.Value); } foreach (var parameter in parsedTemplate.Parameters) {foreach (var inlineConstraint in parameter.InlineConstraints) {Console.WriteLine(parameter.Name + ":" + inlineConstraint.Constraint); var routeConstraint = constraintResolver.ResolveConstraint(inlineConstraint.Constraint); var routeDirection = RouteDirection.IncomingRequest; bool matched = routeConstraint!.Match(httpContext: null, route: null, parameter.Name!, values, routeDirection); Console.WriteLine($"{routeConstraint.GetType().Name} matched: {matched}"); Console.WriteLine();} } } }
输出:
routeTemplate: /{blogApp}/{postType}/{id:int
}/{**slug} TemplateMatcher matched: true blogApp: diary postType: problem id: 681.html slug:id:int
IntRouteConstraint matched: False routeTemplate: /{blogApp}/{postType}/{idOrSlug}.html TemplateMatcher matched: true blogApp: diary postType: problem idOrSlug: 681.html
通过以上代码,我们可以看到 TemplateMatcher 成功匹配了 URL 路径,并正确应用了类型约束。在第一个匹配的例子中,我们使用了 ”/{blogApp}/{postType}/{id:int
}/{**slug}” 的 route template,其中 id 参数被指定为整数类型约束。在匹配过程中,我们可以看到 IntRouteConstraint 成功被应用,并返回了匹配结果。
结论
通过分析源代码和查找相关线索,我们成功解决了 TemplateMatcher 忽略类型约束的问题。我们使用 DefaultInlineConstraintResolver 创建了一个 IRouteConstraint 的实例,并将解析出的类型约束传递给它。这样,在进行 URL 路径匹配时,TemplateMatcher 会正确应用类型约束,从而得到准确的匹配结果。
ASP.NET Core 的 TemplateMatcher 是一个强大的工具,可以帮助我们处理 URL 路由的匹配。然而,在使用它时,我们需要注意到一些潜在的问题,比如忽略类型约束。通过本文提供的解决方案,我们能够充分利用 TemplateMatcher 的功能,并确保类型约束得到正确应用。 文章来源:https://www.toymoban.com/diary/problem/681.html
注意
以上代码仅为示例,可能需要根据您的实际需求进行适当修改。
可以参考以下资料: 文章来源地址 https://www.toymoban.com/diary/problem/681.html
[Stack Overflow](stackoverflow.com)
[Microsoft Documentation](docs.microsoft.com/en-us/aspnet/core/?view=aspnetcore-5.0)
到此这篇关于 ASP.NET Core: TemplateMatcher 忽略类型约束问题的解决方法的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!
原文地址:https://www.toymoban.com/diary/problem/681.html
如若转载,请注明出处:如若内容造成侵权 / 违法违规 / 事实不符,请联系站长进行投诉反馈,一经查实,立即删除!