【问题标题】:Route Attribute isn't producing pretty URLsRoute Attribute 没有产生漂亮的 URL
【发布时间】:2017-06-26 08:51:20
【问题描述】:

我正在使用 ASP.net MVC5,我有以下内容:

[Route("Edit/{id}")]
[HttpGet]
public ActionResult Edit(int id)
{
    // do stuff
    return View(viewModel);
}

[Route("Edit")]
[HttpPost]
public ActionResult Edit(DraftViewModel draft)
{
    if (!ModelState.IsValid) return View(draft);
    // do stuff
    return RedirectToAction("Index");
}

我希望这会产生像这样的漂亮 URL:

草稿/编辑/5

相反,我得到了这个:

草稿/编辑?id=5

这是为什么?如何使用基于属性的路由获得漂亮的 URL?生成带有丑陋 URL 的链接的代码是这样的:

@Html.ActionLink("Edit", "Edit", "Draft", new { id = draft.Id }, new { @class = "btn btn-primary btn-xs" })

更新

当我删除[POST] 操作并且只有[GET](当然没用)时,GET 上的 URL 看起来很漂亮!因此,当我有两条同名(但动词不同)的路线时,框架就会出错!

【问题讨论】:

  • 什么产生了Draft/Edit?id=5?你能分享那个代码吗?
  • @Shyju 我已经添加了那个代码

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


【解决方案1】:

确保RouteConfig在基于约定的路由之前已启用属性路由

routes.MapMvcAttributeRoutes();

正如您已经发现的那样,当您使用不同参数的 POST 操作来获取路由表时,在生成 URL 时使用不同的格式,因为 Asp.Net MVC 框架正在使用约定。

如果您更新 POST 操作的 url 模板以匹配 GET 的格式,它将按需要工作。

[Route("Edit/{id:int}")]
[HttpGet]
public ActionResult Edit(int id) {
    // do stuff
    return View(viewModel);
}

[Route("Edit/{id:int?}")]
[HttpPost]
public ActionResult Edit(DraftViewModel draft) {
    if (!ModelState.IsValid) return View(draft);
    // do stuff
    return RedirectToAction("Index");
}

使 POST 路由模板 id 参数可选,这样您就不必更新操作签名。

来自 ...的结果 URL

@Html.ActionLink("Edit", "Edit", "Draft", new { id = draft.Id }, new { @class = "btn btn-primary btn-xs" })

应该是

草稿/编辑/5

【讨论】:

  • 谢谢@Nkosi!为什么我需要在[HttpPost] Edit 再次通过id
  • @Ciwan - 从技术上讲,你没有。使用属性时,默认情况下它们在路由表中的放置顺序是未定义的。您可以使用 Nkosi 的解决方案来解决此问题,也可以将 Order 属性放在每个 [Route] 属性上,以指定它们在路由表中的顺序。见rion.io/2015/11/13/…。无论您如何解决它,特定路线都需要在一般路线之前先在表格中。
  • @Ciwan NightOwl 是对的。我完全忽略了RoutAttributeOrder 属性。
  • @NightOwl888 对我不起作用,请参阅我对他的回答的评论
  • @Ciwan 检查更新的答案。更新了路由模板以使 id 可选且不必更新操作。仍然有效。
【解决方案2】:

属性路由在大多数的情况下都有效。但是使用属性路由的一个主要缺点是order of attributes are undefined。由于在 MVC 路由中,放置到路由表中的路由的顺序对其正常工作至关重要,因此您需要确保在它们不明确时使用 [Route] 属性的 Order 属性。

在路由中,第一个匹配总是获胜,因此将specific routes before general routes 放在路由表中是绝对关键的。

[Route("Edit/{id}", Order = 1)]
[HttpGet]
public ActionResult Edit(int id)
{
    // do stuff
    return View(viewModel);
}

[Route("Edit", Order = 2)]
[HttpPost]
public ActionResult Edit(DraftViewModel draft)
{
    if (!ModelState.IsValid) return View(draft);
    // do stuff
    return RedirectToAction("Index");
}

参考:http://rion.io/2015/11/13/understanding-routing-precedence-in-asp-net-mvc/

【讨论】:

  • 我试过了,但是没有用。 [POST] 不起作用。当我发布表格时,I see this。但是,链接看起来确实很漂亮,但是没有发布功能,那就不行了!
猜你喜欢
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-24
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
相关资源
最近更新 更多