C# Core MVC 如何将自定义 URL 应用于控制器操作

C# Core MVC How to apply custom URL to controller action

问题:

编辑:看来我的问题实际上不是路由问题而是锚定问题。

如果我分配了路线:

[Route("~/Envelope/List/AcademicYear/{year}")] 
public IActionResult AcademicYear(string year)
{
}

如何正确使用 asp-action 来调用此路由? 使用

<a asp-action="List/AcademicYear/" asp-route-id="@Model.AcademicYear">@Model.AcademicYear</a>

returns a url with a %2f (Envelopes/List%2fAcademicYear/2122) 而不是 / (Envelopes/List/AcademicYear/2122) 从而导致404 错误

如何使用自定义 URL 和 asp-action 在我的控制器中调用特定的 Action?

如何更改路由以便我可以从具有非默认路由映射的控制器调用操作?

上下文:

我读过https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0 但我仍然对路由的整个概念以及如何与控制器和操作进行交互感到困惑。

在我的应用程序中,我有一个名为 Envelope 的控制器 - 它控制与我的 Envelope 相关的一切。

我在 Envelopes 控制器中有一个 class 叫做

public class EnvelopeController : Controller {

 public IActionResult List() {... return View()}

它 return 是 List.cshtml 视图。当前 url 默认路由映射设置:/Envelope/List

在 List.cshtml 中,我有一个 link 旨在根据年份参数过滤列表

<a asp-action="AcademicYear" asp-route-academicYear="@Model.AcademicYear"> @Model.AcademicYear</a>

我的目的是将其传递到 Envelopes 控制器中名为“AcademicYear”的方法中,该方法收集存储在临时数据中的 Envelope 数据,对其进行反序列化,然后 returns 基于参数的过滤版本:

public IActionResult AcademicYear(string academicYear) { return View("List", newViewModel)}

这一点之后的returnurl是正确的:/Envelope/AcademicYear?academicYear=21%2F22

但是我想知道如何更改它,即使我调用了 Action

<a asp-action="AcademicYear" asp-route-academicYear="@Model.AcademicYear"/>

URL returned 看起来像这样 /Envelope/List/AcademicYear/2122/

有办法吗?我是否以错误的方式看待问题?我考虑过简单地在 List 操作中传递一个参数和 运行 某种形式的控制来根据参数的存在来执行任何一组操作,但实际上 List 方法和过滤 AcademicYear 方法并没有真正做同样的事情事情,如果可能的话,我想把代码分成不同的方法。

即使它不是合适的解决方案,我仍然想知道是否可以在调用动作后更改 URL 路由。

编辑 : 我试过使用 HttpGet(List/AcademicYear/{academicYear:[a-zA-Z]} 但是当我这样做时我实际上不能调用 List/AcademicYear 作为 asp-action 由于“/”以及它如何编码为 %2f

回答:

在以下解决方案的帮助下,我意识到我看错了问题,实际上在创建正确的锚点时遇到了问题。

阅读:https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0#url-generation-and-ambient-values-1

我意识到答案就在眼前,我将其与答案中提供的路线一起使用

<a id="@academicYear.Name" href="@Url.Action("AcademicYear", "Envelope",new {year= academicYear.Name})">

也许你只需要这样装饰你的动作:

[HttpGet("List/AcademicYear/{year:int}")] // or HttpPost it depends on you
public IActionResult AcademicYear(string year) { }

您可以为动作添加多个属性路由。

[Route("~/Envelope/List/AcademicYear/{year}", Name="ListRoute")]
[Route("~/Envelope/AcademicYear/{year}")] 
public IActionResult AcademicYear(string year) { }

如果你需要这个url

http://localhost:xxxx/Envelope/List/AcademicYear/2021

您可以使用这个 html 助手,它将使用属性路由名称为您创建一个正确的锚标记。

@Html.RouteLink(@Model.AcademicYear, "ListRoute", new { year = @Model.AcademicYear })

我在属性路由中添加了 Name="ListRoute"(见上文)