Url.Action 结果不会使用 Route 属性进行解析
本文关键字:属性 Route 结果 Action Url | 更新日期: 2023-09-27 17:56:39
我正在重建应用程序的前端,由于其复杂性,我必须在现有的遗留业务层上工作。因此,我们有所谓的"新闻"和"文档",但实际上两者都是存储它的"文档"。
我制作了一个文档控制器,它可以很好地处理所有事情,在控制器上拍打[Route("News/{action=index}")]
和[Route("Documents/{action=index}")]
允许我将控制器称为新闻或文档。目前为止,一切都好。使用具有属性[Route("Documents/View/{id}"]
和[Route("News/View/{id}"]
的单个ActionResult
查看特定文档也可以正常工作。但是,当我尝试使用id
以外的任何参数作为参数但仅用于新闻部分时,我遇到了一个问题。
我的ActionResult
方法具有以下定义
[Route("Documents/Download/{documentGuid}/{attachmentGuid}")]
[Route("News/Download/{documentGuid}/{attachmentGuid}")]
public ActionResult Download(Guid documentGuid, Guid attachmentGuid)
...
我的观点有以下内容来获取链接
<a href="@Url.Action("Download", "Documents", new { documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId })">Download</a>
每当我以"文档"作为控制器时,这将生成一个类似于site/Documents/Download/guid/guid
完美的链接,但是如果我将"新闻"放在那里,我会生成一个 URL,该 URL 使用类似于site/News/Download?guid&guid
参数的查询字符串并解析为 404。如果我然后手动删除查询字符串令牌并手动格式化 URL,它将很好地解决。
这里出了什么问题,是我错过了什么冲突?
在传入请求上查找路由时,路由将使用 URL 来确定哪些路由匹配。您的传入 URL 是唯一的,因此工作正常。
但是,在查找要生成的路由时,MVC 将使用路由值来确定哪些路由匹配。URL (News/Download/
) 中的文字段在此过程的这一部分被完全忽略。
使用属性路由时,路由值派生自所修饰方法的控制器名称和操作名称。因此,在这两种情况下,您的路由值均为:
| Key | Value |
|-----------------|-----------------|
| controller | Documents |
| action | Download |
| documentGuid | <some GUID> |
| attachmentGuid | <some GUID> |
换句话说,您的路径值不是唯一的。因此,路由表中的第一场比赛始终获胜。
若要解决此问题,可以使用命名路由。
[Route("Documents/Download/{documentGuid}/{attachmentGuid}", Name = "Documents")]
[Route("News/Download/{documentGuid}/{attachmentGuid}", Name = "News")]
public ActionResult Download(Guid documentGuid, Guid attachmentGuid)
...
然后,使用 @Url.RouteUrl
或 @Html.RouteLink
解析 URL。
@Html.RouteLink("Download", "News", new { controller = "Documents", action = "Download", documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId })
或
<a href="@Url.RouteUrl("News", new { controller = "Documents", action = "Download", documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId })">Download</a>
Url.Action 的参数是控制器的名称和操作的名称,它仅适用于文档,因为巧合的是,您的路由对应于正确的名称。如果要使用特定路由,则必须命名路由,然后使用采用路由名称的方法之一来构造它。