我对如何在Web应用程序中处理单数和复数路由和控制器感到困惑。
该网站是一个简单的报价网站 - 认为爱因斯坦,莎士比亚等不是保险。在项目中,我有一个名为`QuoteController'的控制器。控制器名称是单数,这是否意味着控制器应该只处理单引号的显示? I.E.
/quote/love-is-a-battlefield-1
我是否需要另一个控制器来显示多个引号(复数)?例如:
/quotes/ (would default to most recent)
/quotes/new
/quotes/shakespeare
/quotes/popular
为单数和复数路线设置单独的控制器是惯例还是良好实践?我希望这是有道理的。
答案 0 :(得分:36)
仅仅因为asp-mvc的默认控制器具有单数名称,这并不意味着你应该为所有控制器实现单数形式。
正确的答案是:取决于您的控制器所代表的实体数量。
奇异,例如AccountController
是单数,因为它代表与单个帐户相关的操作(操作方法)。
多个如果您的控制器包含至少一个在单个事务处理多个实体的操作方法。
多种格式示例
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)
我认为英语语法应该严格地纳入每个编程方面。它读起来更自然,并带来良好的代码卫生。
答案 1 :(得分:6)
这是程序员StackExchange中提出的question,它建议保持类名称的单数。我特别喜欢其中一个答案中的逻辑,“拧螺丝的工具叫做”螺丝刀“而不是”螺丝刀“。”我同意。这些名字应该保留为名词和形容词。
就路由而言,最佳实践似乎倾向于路由是多元化名词,并避免使用动词。这个Apigee blog说,“避免混合模型,在这种混合模型中,您对某些资源使用单数,对其他资源使用复数。保持一致性允许开发人员在学习使用API时预测和猜测方法调用。 “并建议使用基于热门网站所做的单数或复数。他们在路线中使用单数名词的唯一例子是Zappos网站,其中http://www.zappos.com/Product为路线;但是,如果您检查该网站,它不是一个到产品资源的路径,而是一个查询,可能是他们所有的产品。您可以输入http://www.zappos.com/anything并获取结果页面。所以我不会在这方面投入过多的资金。
来自mwaysolutions(随机查找)的其他博客如this说“使用名词但没有动词”和“使用复数名词”。除了其他方面,大多数博客/文章倾向于说同样的事情。多个名词,没有动词。
TL; DR:使用控制器的单数名词和路线的复数名词。
控制器和路由代表两个不同的概念。控制器是一个类或蓝图。与压模类似,我不会说我有一个UnicornsStamper
我会说我有一个UnicornStamper
,它上面印有一只独角兽,我可以用它来制作一套独角兽邮票。集合,作为位字段的枚举类型,作为属性集合的静态类(像集合一样),可能还有一些其他边缘情况,我使用复数名称。
A(n)URL是资源的地址,因此名称为统一资源定位器。我不同意“路线 IS 查询”。路由可以包含查询(查询字符串)以缩小返回的资源,但路由是所请求的位置或资源。
随着属性路由的出现,控制器的多路径就像在[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
免责声明:我把这些属性写在了我的头顶,可能会有一些小的差异需要解决,但希望如何让这些路线发挥作用的要点来了。
希望这有助于消除关于控制器主题和路由命名约定的最佳实践的一些混淆。最终,决定使用复数或单一控制器或路由取决于开发人员。无论如何,一旦你选择了最佳实践,就要保持一致。
答案 2 :(得分:2)
控制器的名称可以是基于其执行的逻辑的复数或单数。我们最有可能将控制器名称保持为单数,因为ProductController听起来比ProductsController好一点。
/product/list or /products/list
/product/add or /products/add
您可以同时使用两者。但你必须保持一致性,你不应该混合它们。对于每个实体类型,所有URL都应该是复数,或者所有URL都应该是单数。
在ASP.NET示例中,他们使用了Singular控制器名称,例如HomeController,AccountController。对于HomeController,您不能使用HomesController,因为它不再代表当前站点Home。
关于逻辑,我们主要是为每个数据库实体创建Controller,我们在其中推断Controller表示要对“Entity”执行的动作因此最好使用Singular控制器名称并且没有任何危害。
只有当你想要创建一组Controller来表示一些看起来像或者映射到多个数据库表名的集合时,你才可以将其命名为复数。
答案 3 :(得分:1)
好问题。本网站的一些贡献者会建议您尝试Programmers网站,但我愿意尝试回答您的问题。
ASP.NET MVC中的路由机制在概念上基于Resource-oriented architecture; ROA的共同准则是
应用程序应公开许多URI(可能是无限数量的URI),每个资源一个(应用程序中的任何资源都应通过唯一的URI明确访问)
因此,由您来决定quote
和quotes
是否是两种不同的资源。
答案 4 :(得分:0)
对于WebAPI,它应该是复数。微软有例子。在此示例中,WebAPI是复数形式。这是链接
https://docs.microsoft.com/en-us/odata/webapi/built-in-routing-conventions
在第一个示例中是OrdersController。在最后两页中,有ProductsController,它是复数形式。 REST命名约定也对此严格。链接应为复数形式。在C#中完成此操作的简单方法是使用复数名称创建控制器
对于MVC,它应该是单个控制器