第一季度
该文档明确指出 API 版本控制“使其变得容易”,而不是“使其更容易”或“是首选”。
我不同意基于约定的路由必然“难以支持”(前提是您了解路由的工作原理)。但是,如果您没有使用在项目中的多个控制器之间共享的约定,那么如果您使用属性路由,则需要维护的代码要少得多。也就是说,您不必在代码中的每个路由上指定要使用的控制器和操作,因为RouteAttribute 知道它本机配对的操作/控制器。
但正如文档所指出的,将所有路线放在一个地方也有其优点。如果您的 API 可以使用适用于多个/所有控制器的约定,那么设置一个约定比多个路由属性更容易维护。
对于那些使用内置 MapRoute 方法可能“难以支持”的约定,您可以根据需要使用自己的扩展方法扩展基于约定的路由,甚至可以继承 RouteBase 类来定义它们你喜欢。
第二季度
排序是属性路由的问题。事实上,属性路由使查看路由注册的顺序变得更加困难。并非所有路由都对顺序敏感,因此在很多时候这不是问题。
但是,当您确实遇到属性路由的排序问题时,它比使用基于约定的路由时要微妙得多。属性do not guarantee any order 当反射检索它们时。因此,无论您在控制器操作中指定的顺序如何,默认顺序都是未知的。
修复属性路由的顺序很容易。只需指定属性的 Order 属性(在较高值之前评估较低的值)。
也就是说,有no way to specify order between different controllers,所以它最终可能会咬你。如果发生这种情况,唯一的内置替代方案是基于约定的路由。
第三季度
我不能给出一个具体的例子来说明你可以在哪里使用属性路由,而你不能使用基于约定的路由(而 AFAIK,没有一个)。以属性路由不支持的方式使用基于约定的路由的一个示例是使data-driven CMS routes。
属性路由支持基于约定的路由支持的功能的子集。它在技术上并不比基于约定的路由更先进。基于约定的路由使您能够直接指定自己的RouteBase(或Route)子类,这使您可以做许多使用内置属性路由无法做到的事情,例如制作基于在子域、查询字符串值、表单帖子值或 cookie 上。您甚至可以在高级场景中制作generate routes based on conventions 的扩展方法。
不借助反射就无法以这种方式扩展属性路由,因为它使用的许多类型都标记为内部类型。
但有 3 个令人信服的理由您可能会考虑使用属性路由而不是基于约定的路由,具体取决于您的项目:
- 它将路由与控制器代码的其余部分放在上下文中,这样可能更容易维护。
- 这意味着您无需在每个路由定义中键入(或复制和粘贴)控制器和操作名称。在可维护性方面,维护路由和控制器之间的这种关系(并解决问题时)可能比将所有路由定义在一个地方的成本更高。
- 属性路由比基于约定的路由更容易学习。如果您的截止日期很紧和/或您的团队对路由缺乏经验,那么使用属性路由可能是更好的选择,因为学习曲线更短。
从中得到的好处是:使用在您的项目中最容易维护的路由类型。如果您有很多类似的模式,请使用基于约定的路由。如果您的 URL 在整个项目中不一致或不规则,或者您只是希望在工作时在与操作方法相同的上下文中查看 URL,请考虑属性路由,但请记住,基于约定的路由是另一种选择。
注意:我链接到的大多数示例都是针对 MVC,而不是 Web API。两个框架之间的路由非常相似(实际上大部分代码类都是共享的)。就基于属性/约定的路由而言,相同的概念可以在 MVC 和 Web API 中使用,但请注意,如果您使用 Web API,则需要定位 System.Web.Http 命名空间而不是 System.Web.Mvc 命名空间并且您想利用这些示例。