Url.Action结果无法使用Route属性解析

时间:2016-07-12 13:51:17

标签: c# asp.net-mvc asp.net-mvc-5 asp.net-mvc-routing attributerouting

我正在重建应用程序的前端,由于其复杂性,我必须处理现有的遗留业务层。因此,我们有一些名为" News"和"文件"但实际上两者都是"文件"存储的地方。

我已经制作了一个DocumentsController来处理一切正常,在控制器上打一个[Route("News/{action=index}")][Route("Documents/{action=index}")]允许我将控制器称为新闻或文档。到现在为止还挺好。使用具有属性ActionResult[Route("Documents/View/{id}"]的单个[Route("News/View/{id}"]查看特定文档也可以正常工作。但是,当我尝试使用除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>

只要我有&#34;文件&#34;这将完美地生成类似于site/Documents/Download/guid/guid的链接。作为控制者,但如果我把&#34;新闻&#34;在那里我得到一个生成的URL,它使用类似于site/News/Download?guid&guid参数的查询字符串并解析为404.如果我然后手动删除查询字符串并手动格式化URL,它将解决不错。

这里出了什么问题,我错过了哪些相互矛盾的东西?

2 个答案:

答案 0 :(得分:1)

您的Url.Action的参数是控制器的名称和操作的名称,它仅适用于文档,因为巧合,您的路线对应于正确的名称。如果要使用特定路由,则必须为路由命名,然后使用采用路由名称构建它的方法之一。

答案 1 :(得分:1)

在传入请求中查找路由时,路由将使用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解析网址。

@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>