ASP.NET Core 2 MVC中Tag Helper生成带斜杠路由链接的问题
解决ASP.NET Core MVC中动作链接斜杠被转义的问题
你遇到的问题本质上是ASP.NET Core MVC的标签助手对控制器名称的解析逻辑和MVC5的Html.ActionLink不一样——Core里的asp-controller属性只接受纯控制器名称(即去掉Controller后缀的类名),当你传入带斜杠的Manage/Accounts时,它会把斜杠当作控制器名称的一部分进行URL转义,而不是解析成路由层级。
下面给你几个符合Core设计规范的解决方案:
方案1:利用路由属性的占位符简化配置
调整控制器的路由属性,用[Controller]占位符自动获取控制器名称,这样就不需要在标签助手里指定带路径的控制器名:
控制器代码
[Route("Manage/[Controller]")] public class AccountsController : Controller { // 默认路由:Manage/Accounts/Index [Route("[Action]")] public IActionResult Index() => View(); // 路由:Manage/Accounts/Other [Route("[Action]")] public IActionResult Other() => View(); }
视图链接代码
<a asp-controller="Accounts" asp-action="Index">Accounts</a> <a asp-controller="Accounts" asp-action="Other">Accounts (Other)</a>
这样生成的HTML会是你期望的格式:
<a href="/Manage/Accounts">Accounts</a> <a href="/Manage/Accounts/Other">Accounts (Other)</a>
方案2:使用Area实现嵌套功能结构(推荐)
如果你的目标是实现类似MVC5的功能文件夹嵌套,ASP.NET Core的Area是官方推荐的模块化方案,比自定义视图引擎更符合框架设计:
1. 创建Area结构
在项目根目录创建Areas/Manage/Controllers目录,把AccountsController放到这个目录下。
2. 控制器添加Area属性
[Area("Manage")] public class AccountsController : Controller { public IActionResult Index() => View(); public IActionResult Other() => View(); }
3. 配置Area路由
在Startup.cs的Configure方法里添加Area路由规则:
app.UseMvc(routes => { // 配置Manage区域的路由 routes.MapAreaRoute( name: "ManageArea", areaName: "Manage", template: "Manage/{controller=Home}/{action=Index}/{id?}"); // 默认路由 routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
4. 视图生成链接
使用asp-area指定区域,配合asp-controller和asp-action:
<a asp-area="Manage" asp-controller="Accounts" asp-action="Index">Accounts</a> <a asp-area="Manage" asp-controller="Accounts" asp-action="Other">Accounts (Other)</a>
这个方案不仅能解决URL转义问题,还能更好地组织你的模块化代码,后续维护更方便。
方案3:手动指定路由名称(适合特殊场景)
如果一定要保留原有的路由属性写法,可以给每个动作指定路由名称,然后通过名称生成链接:
控制器代码
[Route("Manage/Account")] public class AccountsController : Controller { [Route("[Action]", Name = "AccountsIndex")] public IActionResult Index() => View(); [Route("[Action]", Name = "AccountsOther")] public IActionResult Other() => View(); }
视图链接代码
<a href="@Url.RouteUrl("AccountsIndex")">Accounts</a> <a href="@Url.RouteUrl("AccountsOther")">Accounts (Other)</a>
这种方式需要给每个动作单独命名,适合少量特殊路由的场景,不推荐大规模使用。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

