2016-06-15 311 views
17

這些功能的根本區別是什麼?我所知道的全是201中的三個結果,這對於成功的POST請求是適當的。ASP.net Core RC2 Web API POST - 何時使用Create,CreatedAtAction,還是CreatedAtRoute?

我只遵循我在網上看到的例子,但他們並沒有真正解釋他們爲什麼要做他們正在做的事情。

我們應該爲我們的GET(1個記錄ID)提供一個名稱:

[HttpGet("{id}", Name="MyStuff")] 
public async Task<IActionResult> GetAsync(int id) 
{ 
    return new ObjectResult(new MyStuff(id)); 
} 

什麼是命名這個獲取函數,除了它的「可能」需要的POST功能的目的如下:

[HttpPost] 
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff) 
{ 
    // actual insertion code left out 

    return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff); 
} 

我注意到,CreatedAtRoute也有一個重載不包含路由名稱。

也有CreatedAtAction,採取相似的參數。爲什麼這個變體存在?

也有Created它預計URL和我們想要返回的對象。我可以只使用這個變體,並提供一個僞造的URL並返回我想要的對象,並完成它並結束?

我不知道爲什麼有這麼多的變種只是爲了能夠返回201到客戶端。在大多數情況下,我想要做的就是返回「應用程序分配」(最可能來自數據庫)唯一標識或具有最少信息的實體版本。

我認爲最終,201應答「應該」創建一個位置標題,其中包含新創建資源的URL,我相信所有3和它們的重載最終都會執行。爲什麼我應該總是返回一個位置標題?我的JavaScript客戶端,原生移動設備和桌面應用程序從不使用它。例如,如果我發出HTTP POST,要創建帳單聲明並將其發送給用戶,那麼這樣的位置URL會是什麼? (對於不深入互聯網的歷史尋找答案,我深表歉意。)

爲什麼要爲動作和路由創建名稱?動作名稱和路由名稱之間有什麼區別?

我對此感到困惑,所以我採取了返回Ok(),返回200,這是不適合POST。

回答

22

這裏有幾個不同的問題可能會被拆分出來,但我認爲這涵蓋了大部分問題。

爲什麼要爲動作和路線創建名稱?動作名稱和路由名稱之間有什麼區別?

首先,動作和路線是非常不同的。

一個Action存在於一個控制器上。路由指定了一個完整的終點,該終點由一個Controller和Action以及潛在的附加其他路由參數組成。

您可以爲路線指定一個名稱,以便您在應用程序中引用它。例如

routes.MapRoute(
    name: "MyRouteName", 
    url: "SomePrefix/{action}/{id}", 
    defaults: new { controller = "Section", action = "Index" } 
); 

原因操作名稱都屬於這樣一個問題:Purpose of ActionName

它可以讓你以數字開頭,你的行動或包括.NET不以允許任何字符標識符。 - 最常見的原因是它可以讓你有兩個操作具有相同簽名(見GET/POST刪除任何腳手架控制器的動作)

什麼是這些職能的根本區別是什麼?

這3個函數都執行基本相同的功能 - 返回201 Created響應,Location標題指向新創建的響應的url,以及正文中的對象本身。該網址應該是GET請求將返回對象網址的網址。這將被視爲RESTful系統中的「正確」行爲。

對於您的問題中的郵政編碼示例,您實際上需要使用CreatedAtAction

[HttpPost] 
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff) 
{ 
    // actual insertion code left out 

    return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff); 
} 

假設你已經配置了默認路由,這將增加Location頭指向同一個控制器上的MyStuff行動。

如果你想要的位置URL指向一個特定的路線(如我們前面所定義的,你可以使用如

[HttpPost] 
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff) 
{ 
    // actual insertion code left out 

    return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff); 
} 

可我只是用這個變種並提供虛假的URL,並返回對象我想要得到它完成,在用?

如果你真的不想使用CreatedResult,你可以使用一個簡單StatusCodeResult,它會返回一個201,沒有Location頭或身體。

[HttpPost] 
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff) 
{ 
    // actual insertion code left out 

    return StatusCode(201); 
} 
+0

我不確定.NET核心,但'內容(HttpStatusCode,T內容)'方法仍然存在以返回狀態碼和內容?這應該允許返回201以及新創建的對象,而不包括'Location'頭。 – afrazier

+1

該重載似乎不再存在,但實際上有一個可以類似使用的StatusCode重載:'StatusCode(int httpStatusCode,object value)' – Sock

+1

似乎'[HttpGet(「{id}」) ,Name =「GetUser」,Order = 0)]創建路線的方式似乎不適用於CreatedAtRoute() – Crob

相關問題