ASP.NET Core 8如何复现3.1移除的环境路由值链接生成功能?
在ASP.NET Core 8 Razor Pages复现环境路由值功能的方案
官方移除自动继承环境路由值的功能后,确实需要通过自定义扩展来实现,最直接的方式是自定义AnchorTagHelper或扩展UrlHelper,以下是具体实现方案:
方案一:自定义AnchorTagHelper(推荐用于页面链接)
通过继承默认的AnchorTagHelper,自动从当前页面路由上下文提取目标页面需要的参数,无需手动编写asp-route-*属性。
1. 实现自定义TagHelper类
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; [HtmlTargetElement("a", Attributes = "asp-page, asp-auto-inherit-routes")] public class AutoInheritRouteAnchorTagHelper : AnchorTagHelper { private readonly IPageContextAccessor _pageContextAccessor; public AutoInheritRouteAnchorTagHelper( IHtmlGenerator generator, IPageContextAccessor pageContextAccessor) : base(generator) { _pageContextAccessor = pageContextAccessor; } [HtmlAttributeName("asp-auto-inherit-routes")] public bool AutoInheritRoutes { get; set; } = true; public override void Process(TagHelperContext context, TagHelperOutput output) { if (AutoInheritRoutes && !string.IsNullOrEmpty(PageName)) { var currentRouteValues = _pageContextAccessor.PageContext.RouteData.Values; // 获取目标页面的路由模板参数 var targetPage = _pageContextAccessor.PageContext.ActionDescriptor.EndpointMetadata .OfType<PageRouteMetadata>() .FirstOrDefault(p => p.RelativePath == $"/{PageName.Replace("~/", "").TrimStart('/')}.cshtml"); if (targetPage != null) { var targetParams = targetPage.RouteTemplate.Split('/') .Where(segment => segment.StartsWith("{") && segment.EndsWith("}")) .Select(segment => segment.Trim('{', '}')) .ToList(); // 自动添加当前路由中存在、目标页面需要且未手动指定的参数 foreach (var kvp in currentRouteValues) { if (targetParams.Contains(kvp.Key) && !RouteValues.ContainsKey(kvp.Key)) { RouteValues[kvp.Key] = kvp.Value; } } } } base.Process(context, output); } }
2. 注册TagHelper
在项目的_ViewImports.cshtml中添加TagHelper引用(替换YourProjectAssembly为你的项目程序集名称):
@addTagHelper *, YourProjectAssembly
3. 页面中使用
只需添加asp-auto-inherit-routes属性,即可自动携带匹配的路由参数:
@page "/org/{org}/projects/{project}" @model Details <a asp-page="/Translate/Index" asp-auto-inherit-routes> Translate </a>
方案二:扩展UrlHelper(用于代码生成URL)
如果需要在后台或视图代码中生成URL,可以扩展UrlHelper实现自动继承路由参数:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Routing; public static class UrlHelperExtensions { public static string PageWithInheritedRoutes(this IUrlHelper urlHelper, string pageName, object? routeValues = null) { var currentRouteValues = urlHelper.ActionContext.RouteData.Values; var targetPage = urlHelper.ActionContext.ActionDescriptor.EndpointMetadata .OfType<PageRouteMetadata>() .FirstOrDefault(p => p.RelativePath == $"/{pageName.Replace("~/", "").TrimStart('/')}.cshtml"); var mergedRouteValues = new RouteValueDictionary(routeValues); if (targetPage != null) { var targetParams = targetPage.RouteTemplate.Split('/') .Where(s => s.StartsWith("{") && s.EndsWith("}")) .Select(s => s.Trim('{', '}')) .ToList(); foreach (var kvp in currentRouteValues) { if (targetParams.Contains(kvp.Key) && !mergedRouteValues.ContainsKey(kvp.Key)) { mergedRouteValues[kvp.Key] = kvp.Value; } } } return urlHelper.Page(pageName, mergedRouteValues); } }
使用方式
@inject IUrlHelper Url <a href="@Url.PageWithInheritedRoutes("/Translate/Index")">Translate</a>
注意事项
- 确保
IPageContextAccessor已在DI容器中注册,ASP.NET Core 8默认已注册,若未注册可在Program.cs添加:builder.Services.AddSingleton<IPageContextAccessor, PageContextAccessor>(); - 可根据需求调整自定义逻辑,比如只继承特定前缀的参数(如
org、project),避免意外携带无关参数。
内容的提问来源于stack exchange,提问作者Peter Kneale
相关产品推荐
相关产品推荐

