属性与常规路由

Attribute vs Conventional Routing

Q1:所以这个 article 说属性路由比 api 版本控制的常规路由更有利。我不清楚这种说法背后的原因,因为对我来说,为了支持这些:

/api/v1/products
/api/v2/products

您需要做的就是定义两条路线:

routes.MapHttpRoute("V1", "api/v1/products",    new {controller = "V1Controller", action = "ListProducts"});
routes.MapHttpRoute("V2", "api/v2/products",    new {controller = "V2Controller", action = "ListProducts"});

可以分享一些见解吗?

Q2:this article 说传统路由的一个问题是 table 中条目的顺序,您可能会意外地将请求映射到错误的控制器。为什么这不是属性路由的问题?我的意思是模板只是一个字符串,所以它怎么能阻止我定义两条路由,其中​​一条比另一条更通用?

Q3:谁能举个具体的例子,用属性路由可以实现,而用常规路由不行? - 我不是在谈论代码的可读性和可维护性。

Q1

文档明确指出 "makes it easy" 用于 API 版本控制,而不是 "makes it easier" 或 "is preferred"。

我不同意基于约定的路由一定是 "hard to support"(前提是您了解路由的工作原理)。但是,如果您没有使用在项目中的多个控制器之间共享的约定,那么如果您使用属性路由,则需要维护的代码会少得多。也就是说,您不必在代码中的 每个 路由上指定要使用的控制器和操作,因为 RouteAttribute 知道 action/controller 它在本地配对.

但正如文档所指出的,将所有路线放在一个地方也有其优点。如果您的 API 可以使用适用于 multiple/all 控制器的约定,那么设置一个约定比多个路由属性更容易维护。

对于那些可能 "hard to support" 内置 MapRoute 方法的约定,您可以根据需要使用自己的扩展方法扩展基于约定的路由,甚至继承 RouteBase class 随心所欲地定义它们。

Q2

排序属性路由的问题。事实上,属性路由使得查看路由注册顺序变得更加困难。并非所有路由都对顺序敏感,因此在很多时候这不是问题。

但是,当您 遇到属性路由的排序问题时,它比使用基于约定的路由要微妙得多。反射检索时的属性 do not guarantee any order。因此,无论您在控制器操作中指定的顺序如何,默认顺序都是未知的。

修复属性路由的顺序很容易。只需指定属性的 Order 属性(较低的值在较高的值之前评估)。

也就是说,有 ,所以它最终可能会咬你。如果发生这种情况,唯一的内置替代方案是基于约定的路由。

Q3

我无法给出一个具体的例子来说明在哪些地方可以使用属性路由而哪些地方不能使用基于约定的路由(而且 AFAIK,没有一个)。以属性路由不支持的方式使用基于约定的路由的示例是 .

属性路由支持基于约定的路由所支持功能的 子集。它在技术上并不比基于约定的路由更先进。基于约定的路由让你可以直接指定你自己的RouteBase(或Route)子class,这让你可以做很多内置属性做不到的事情路由,例如创建基于子域、查询字符串值、表单 post 值或 cookie 的路由。您甚至可以在高级场景中制作 的扩展方法。

如果不借助反射,属性路由无法以这种方式扩展,因为它使用的许多类型都标记为内部。

但是有 3 个令人信服的理由可以让您考虑使用属性路由而不是基于约定的路由,具体取决于您的项目:

  1. 它将路由与其余控制器代码放在上下文中,这可能更易于维护。
  2. 这意味着您无需在每个路由定义中键入(或复制并粘贴)控制器和操作名称。就可维护性而言,维护路由和控制器之间的这种关系(并在错误时解决)可能比将所有路由定义在一个地方的成本更高。
  3. 属性路由比基于约定的路由更容易学习。如果您的最后期限很紧 and/or 您的团队没有路由经验,那么使用属性路由可能是更好的选择,因为学习曲线更短。

需要注意的是:使用在您的项目中最容易维护的路由类型。如果您有很多相似的模式,请使用基于约定的路由。如果您的 URL 在整个项目中不一致或不规则,或者您只是想在工作时在与操作方法相同的上下文中查看 URL,请考虑属性路由,但请记住,基于约定的路由是另一种选择。

NOTE: Most of the examples I have linked to are for MVC, not Web API. Routing is very similar (in fact, most of the code classes are shared) between the two frameworks. The same concepts can be used in both MVC and Web API as far as attribute/convention-based routing goes, but do be aware that you need to target the System.Web.Http namespace rather than the System.Web.Mvc namespace if you are using Web API and you want to take advantage of those examples.