30

我对如何在我的 Web 应用程序中处理单复数路由和控制器感到有些困惑。

该网站是一个简单的报价网站 - 想想爱因斯坦、莎士比亚等,而不是保险。在项目中,我有一个名为“QuoteController”的控制器。控制器名称是单数的,那么这是否意味着控制器应该只处理单引号的显示?IE

/quote/love-is-a-battlefield-1

然后我是否需要另一个控制器来显示多个引号(复数)?例如:

/quotes/ (would default to most recent)
/quotes/new
/quotes/shakespeare
/quotes/popular

为单数和复数路由设置单独的控制器是惯例还是良好做法?我希望这是有道理的。

4

4 回答 4

48

仅仅因为 asp-mvc 的默认控制器具有单数名称,并不意味着您应该为所有控制器实现单数形式。

正确答案是:这取决于您的控制器所代表的实体的数量。

Singular,例如 theAccountController是单数的,因为它表示仅与单个帐户相关的操作(操作方法)。

复数如果您的控制器包含至少一个在单个事务中处理多个实体的操作方法。

示例复数格式

users/update/3

上面的路线让你觉得你在编辑所有用户,如果你把它当成一个句子来读是没有意义的。但是,如果您像查询一样阅读您的路线,它会更有意义。

如果我们考虑一下,路线就是一个查询:{entities}/{action}/{parameter}对我来说看起来像是一个查询。

users/users/all“选择所有用户表的简写

users/123读取“从用户表中选择单个实体”

users/update/123读取“从用户表更新单个实体”

主要站点使用复数格式,请参见下面的示例

stackoverflow.com/questions          <- list of questions   (multiple)
stackoverflow.com/questions/18570158 <- individual question (single)
stackoverflow.com/questions/ask      <- new question        (single)

stackoverflow.com/users        <- display list of users (multple)
stackoverflow.com/users/114403 <- individual user       (single)

asp.net/mvc/tutorials        <- display list of tutorials (multiple) 
asp.net/mvc/tutorials/mvc-5  <- individual tutorial       (single)

facebook.com/messages/     <- Display list of messages (multiple)
facebook.com/messages/new  <- Create a single message  (single)
facebook.com/messages/john <- view individual messages (multiple)

我认为英语语法应该严格地融入到每个编程方面。它读起来更自然,并导致良好的代码卫生。

于 2014-01-20T06:58:27.470 回答
13

回答

这是程序员 StackExchange 中提出的一个问题,建议保持类名单一。我特别喜欢其中一个答案中的逻辑,“用来转动螺丝的工具称为“螺丝刀”而不是“螺丝刀”。 我同意。名称应保留为名词和形容词。

就路由而言,最佳实践似乎倾向于将路由作为复数名词,并避免使用动词。这个 Apigee博客说,“避免使用混合模型,在这种模型中,您对某些资源使用单数,而对其他资源使用复数。保持一致允许开发人员在学习使用您的 API 时预测和猜测方法调用。” 并建议根据流行网站的做法使用单数或复数。他们在路由中使用单数名词的唯一示例是 Zappos 站点,该站点以http://www.zappos.com/Product作为路由;但是,如果您检查该站点,它并不完全是产品资源的路径,而是一个查询,可能针对他们所有的产品。你可以输入http://www.zappos.com/anything并获得结果页面。所以我不会投入太多的股票。

来自 mwaysolutions(随机查找)的其他博客,例如“使用名词但没有动词”“使用复数名词”。撇开其他观点不谈,大多数博客/文章倾向于说同样的话。复数名词,没有动词。

TL;DR:控制器使用单数名词,路由使用复数名词。

控制器

控制器和路由代表两个不同的概念。控制器是一个类或蓝图。与压模类似,我不会说我有一个UnicornsStamper我会说我有一个UnicornStamper可以制作独角兽邮票的,我可以用它制作一系列独角兽邮票。集合、作为位字段的枚举类型、作为属性集合的静态类(就像集合一样),以及可能我会使用复数名称的其他一些边缘情况。

路线

A(n) URL 是资源的地址,因此名称为Uniform Resource Locator。我不同意“路线查询”的说法。路线可以包含查询(查询字符串)来缩小返回的资源,但路线是被请求的位置或资源。

随着属性路由的出现,控制器的多元化路由就像在声明中添加[RoutePrefix("quotes")]属性一样简单。QuoteController这也允许更容易设计关联路由。查看原始问题中提供的示例路线:

/quotes GET: Gets all quotes POST: Creates a new quote /authors/shakespeare/quotes Associative route in the QuoteController GET: Gets all Shakespeare quotes /quotes/new This is a bad route IMO. Avoid verbs. Make a POST request to '/api/quotes' to create a new quote /quotes/shakespeare /quotes/popular Although these would be nice to have, they're not practical for routing (see below)

最后两条路线的问题在于,您没有简单的方法来区分流行引用和作者引用,更不用说通过名称或 ID 链接到引用的路线了。您需要用[Route("popular")]后跟[Route("{author}")](按该顺序)修饰的操作,以便路由表以适当的顺序选择路由。但是作者路线消除了拥有路线的可能性[Route("{quoteName}")][Route("{quoteId}")](假设quoteId是一个字符串)。自然,您会希望能够按名称和/或 ID 路由到引号。

稍微偏离主题

最好通过关联路径来获取作者的引用。您仍然可以将流行的路由用作静态路由名称,但此时您正在增加路由复杂性,这将更适合查询字符串。在我的脑海中,如果我真的想在路线中包含流行的搜索词,我可能会这样设计这些路线:

a:/authors/{authorName}/quotes b:/authors/{authorName}/quotes/popular c:/authors/{authorName}/quotes?popular=true d:/quotes/popular e:/quotes/popular?author={authorName} f:/quotes?author={authorName}&popular=true g:/quotes/{quoteName|quoteId}

这些可以分散在QuoteController的行动中。假设控制器有一个[RoutePrefix("quotes")]属性:

[HttpGet] [Route("popular")] [Route("~/authors/{authorName}/quotes/popular")] // Handles routes b, d, & e public ViewResult GetPopularQuotes(string authorName) return GetQuotes(authorName, true); [HttpGet] [Route("")] [Route("~/authors/{authorName}/quotes") // Handles routes a, c, & f public ViewResult GetQuotes(string authorName, bool popular = false) // TODO: Write logic to get quotes filtered by authorName (if provided) // If popular flag, only include popular quotes [HttpGet] [Route("{quoteId}")] // Handles route g public ViewResult GetQuoteById(string quoteId) // TODO: Write logic to get a single quote by ID

免责声明:我在脑海中写下了这些属性,可能存在需要解决的细微差异,但希望如何让这些路线发挥作用的要点能够通过。

希望这有助于消除关于控制器和路由命名约定最佳实践的一些混淆。最终,使用复数或单数控制器或路由的决定取决于开发人员。无论如何,一旦您选择了要遵循的最佳实践,请保持一致。

于 2015-05-26T20:36:50.403 回答
4

根据其执行的逻辑,控制器的名称可以是复数或单数。很可能我们将控制器名称保持为单数,因为 ProductController 听起来比 ProductsController 好一点。

   /product/list    or    /products/list
   /product/add   or    /products/add

您可以同时使用两者。但是你必须保持一致性,你不应该混合它们。对于每个实体类型,所有 URL 都应该是复数,或者所有 URL 都应该是单数。

在 ASP.NET 示例中,他们使用了单数控制器名称,例如 HomeController、AccountController。在 HomeController 的情况下,您不能使用 HomesController,因为它不再代表当前站点 Home。

关于逻辑,我们大多为每个数据库实体创建 Controller,其中我们推断 Controller 表示要在“实体”上执行的操作,所以使用单控制器名称是好的,没有坏处。

只有当你想创建一组控制器来表示应该看起来像或映射到复数数据库表名的东西的集合时,你才能将其命名为复数。

于 2013-09-02T19:53:29.403 回答
1

好问题。该网站的一些贡献者会建议您尝试Programmers网站,但我愿意尝试回答您的问题。

ASP.NET MVC中的路由机制,概念上是基于面向资源的架构;ROA 的共同准则是

应用程序应该公开许多 URI(可能有无数个),每个资源一个(应用程序中的任何资源都应该可以通过唯一的 URI 明确访问)

quote因此,由您决定是否quotes是两种不同的资源。

于 2013-09-02T18:58:21.210 回答