ASP.NET MVC页面遵循RESTful URL约定

时间:2014-01-10 16:52:32

标签: asp.net-mvc asp.net-web-api asp.net-mvc-routing

我们有一个使用经典MVC控制器和WebAPI控制器的项目。经典控制器只提供HTML。使用WebAPI传递任何数据。

我的同事指出RESTful URL标识资源,GET / POST / PUT / DELETE是动词。我很好奇我们是否应该遵循页面本身的相同约定。

我发现使用RESTful约定命名页面确实很困难。例如,区分索引与创建与编辑页面的唯一区别是路由是否包含ID或查询字符串。之前,我刚刚/Account/Account/Create/Account/Edit。使用REST,一切都在/Account之下,我必须根据ID或查询字符串进行区分。我觉得我不应该使用RESTful约定来命名页面。

澄清

在应用程序中传输的任何数据都使用WebAPI。因此,对于一个帐户,我们可以使用以下操作:

GET /accounts - Gets all the accounts
GET /accounts/123 - Gets the account with the ID 123
POST /accounts - Creates a new account
PUT /accounts/123 - Updates account with ID 123
DELETE /accounts/123 - Delete account with ID 123

有时PUT方法假定ID在体内。

普通的MVC控制器返回HTML。在这种情况下,只有永远 GET。 HTML几乎完全是静态的(我们将ID存储在隐藏字段中)。 AJAX用于使用REST API加载数据。

我想知道HTML页面是否应该使用类似REST的URL,或者我是否应该使用旧MVC项目中找到的URL。这是同事提出的建议:

GET /accounts - Gets a screen with all of the accounts
GET /accounts/123 - Gets the HTML for viewing a single account
GET /accounts - Gets the HTML for creating a new account (already in use!)
GET /accounts/123 Gets the HTML for updating an account (already in use!)

由于GET始终是HTTP方法,因此我需要的不仅仅是一个URL来区分屏幕。对于旧的MVC路由,该操作是URL的一部分:

GET /accounts/Index - Gets the screen with all of the accounts
GET /accounts/Index/123 - Gets the screen for a single account
GET /accounts/Create - Gets the screen for creating an account
GET /accounts/Edit - Gets the screen for editing an account

有些答案指出HTML页面只是资源。在我看来,它们只是观点,但还不是另一种资源的真实表现。直到数据被带回并绑定到HTML才是真正的“表示”。考虑到这一点,是不是像任何其他静态内容一样的静态HTML页面,如图像? RESTful URL约定是否适用于图像之类的内容?

2 个答案:

答案 0 :(得分:2)

完成了一个处理RESTful URI并在同一控制器上提供HTML / Json / XML的混合MVC应用程序,这很痛苦。主要问题是当您想要创建/编辑表单时该怎么做。在普通的REST API中,客户端处理这个问题,因此您只需要一个POST /帐户或PUT / account / 123来进行创建。如果你也通过MVC处理客户端,那么完全是另一回事。

可以使用RESTful原则来帮助你进入MVC方面,但唯一完全宁静的部分应该是WebAPI。

如果您使用MVC RESTful路由,那么您本身不应该拥有/ account / create或/ account / edit,因为这些是操作,您现在可以使用资源。通常POST = create和PUT = edit(或者你可以颠倒这个比喻......当你想控制生成的ID时,我更喜欢POST =创建)

我们的解决方案是将表单本身作为资源处理:

GET /account-creation-form
fill form and submit
POST /accounts
Redirect GET /accounts/123
=> 123 is the generated id

我们还有更多问题,因为我们需要在提交表单之前预先生成表单上的ID,这导致要求使用预生成ID的新表单并使用它来创建帐户。

POST /account-creation-forms
Redirect GET /account-creation-forms/123
fill form and submit with pregenerated ID 234
POST /accounts
Redirect GET /accounts/234

正如您所看到的,它很快就会失控。希望大多数应用程序都是基于行动而不是CRUD。如果您有一个简单的CRUD UI(创建/编辑/删除),只需使用标准的MVC路由和原则,并且只确保WebAPI部分是RESTful,这样可以大大简化您的生活。

例如,如何以RESTful方式操作资源,启用/禁用帐户:

GET /accounts/123
POST /disabled-accounts?account=/account/123
Redirect GET /disabled-accounts/123 
=> /accounts/123 doesn't exist anymore

我们实际上是根据用户操作移动资源。当您想要复制或备份文件(资源)时,您也可以这样做。

仍然......如果您有一个WebAPI,请将其作为REST,但如果您想保持理智,请保持标准的CRUD MVC原则。

答案 1 :(得分:0)

在HTTP世界中,您拥有由URI标识的资源,并且您有HTTP方法对其进行操作。您发送请求以对资源执行操作并返回响应。在请求中发送的内容(特定主体)或在响应主体中发送的内容由内容类型指示。对于页面,响应内容类型将只是HTML,以便浏览器可以呈现。因此,如果您将帐户页面视为具有URI http://server/account的资源,您将对此URI进行POST以创建新帐户。您将对URI http://server/account/123进行PUT以更新ID为123的帐户。当然,您可以使用PUT创建资源,但它稍微偏离主题。您将对同一URI进行DELETE以删除它。因此,无论是否有页面,任何资源都可以使用此约定。

在实现方面,网页由浏览器呈现。 HTML表单只能有GET和POST作为操作。因此,为了执行PUT或DELETE,您必须使用诸如使用HtmlHelper.HttpMethodOverride来模拟PUT和DELETE或使用XMLHttp(JavaScript)这样的技巧,但MVC控制器可以具有与这些HTTP方法相对应的动作方法。它有点凌乱,因为MVC适用于类似RPC的路由,而不是像Web API那样的基于HTTP方法的路由。

BTW,从另一个角度来看,你可以让Web API动作方法返回HTML。没有任何API应该只返回JSON或XML。

PS。我不确定我是否解释得这么好,但我认识的一个人能做得更好的是Darrel Miller,但他到目前为止还没有回应,所以我做了,只是为了给我的2c。

修改

http://www.bizcoder.com/experiments-with-katana

  

几个月前,我建立了一个网站http://hypermediaapi.com   意图使用它作为聚合所有事物的链接的地方   超媒体相关。我使用Web API构建了网站,因为a)我知道   如何使用它,以及b)我想证明一个网站是一个点   实际上只是一种特殊类型的Web API 。 - 更多信息请访问:   http://www.bizcoder.com/experiments-with-katana#sthash.SQDlVBNf.dpuf