2016-05-12 4 views
0

Zur Zeit habe ich die folgenden Standardfunktionen in jedem meiner Controller grundlegende CRUD-Operationen zu handhaben:POST Verwendung oder für eine WebAPI Aktion Methode GET, die eine Liste zurückgibt, erfordert aber params

GET /api/todo   Get all to-do items 
GET /api/todo/{id}  Get an item by ID 
POST /api/todo   Add a new item 
PUT /api/todo/{id}  Update an existing item 
DELETE /api/todo/{id} Delete an item 

aber die Zeit kam, wo ich erkannte, dass ich tatsächlich mehrere Parameter übergeben muss, um eine Liste von Todo-Elementen zu erhalten, die auf der Datenbank-Ebene gefiltert werden, anstatt alle Elemente abzurufen und linq zu verwenden.

Zum Beispiel ist hier, wie ich es beschlossen gehen:
In meinem Controller:

// POST: api/todo 
[HttpPost] 
public IList<TodoItem> Get([FromBody]GetTodoItemsRequest request) 
{ 
    return _todoItemManager.GetTodoItems(request.Name, request.CategoryId); 
} 

Wie Sie Ich habe ein neues Modell namens sehen GetTodoItemsRequest, die eine Eigenschaft für jeden haben meine Parameter. In diesem Fall: Name, KategorieId.

Ich dachte, wenn Sie mit mehreren Parametern umgehen und eine Liste abrufen, ist es am besten, POST zu machen und ein Modell speziell dafür zu erstellen. Anstatt ein GET zu verwenden und alle Arten von Informationen in der URL zu übergeben.

Es scheint ein bisschen komisch zu sein, das oben zu tun ... Würde es nicht als eine vollkommen feine Lösung sehen oder gibt es etwas, das mir in der WebAPI-Welt fehlt?

+0

Werfen Sie einen Blick auf http://stackoverflow.com/questions/5020704/how-to-design-restful-search-filtering, bespricht diesen genauen Punkt. –

Antwort

3

Ich glaube, dass semantisch falsch ist, POST Methode für eine einfache Leseoperation zu verwenden, auch wenn Sie ein komplexes Modell benötigen. Sie machen eine reine Abfrage auf Ihrer Ressource namens todo, und dies sollte wirklich ein GET Betrieb aus vielen Gründen:

  1. Es cachable sein soll: POST Anfrage ihrer Natur nach nicht cachable und Caching eine wichtige Einschränkung in RESTful-Diensten.
  2. Es sollte semantisch zeigen, dass keine Nebenwirkung wird aus dem Aufruf erhöht werden: GET Anfragen idempotent sein muss und sicher, POST Operationen, sondern zeigt eine Art von Datenmanipulation. Ihre Operation (Filterung) ist sowohl idempotent als auch sicher, daher sollte sie spontan durch eine GET Anfrage dargestellt werden.
  3. Der Teil der URI nach einem ? Zeichen wird aus einem Grund als Abfragezeichenfolge bezeichnet: es stellt Parameter dar, die den Bereich einer Anfrage weiter spezifizieren. Nun, filtert die Ergebnisse nicht nur ein Beispiel für diesen Ansatz?

Davon abgesehen, scheint es mir, dass, wenn Name und CategoryId Parameter für Ihre Anfrage, Ihre Filteroperation erforderlich sind, besser durch eine andere URI dargestellt werden könnte, in der Name und CategoryId in Routenparameter eingeschaltet werden:

Angenommen, eine Beziehung zwischen Ihrem name Parameter (ein Benutzername vielleicht?) Und dem categories.

Wenn stattdessen Ihre Parameter sind komplett optional, dann als Query-String-Parameter verlassen, ist die beste Wahl:

http://yourhost.com/api/todos?name=nameValue&categoryId=categoryIdValue 

Eine Randbemerkung:
Sie wirklich Plural für Ihre Ressourcen nutzen sollten wenn sie eine Sammlung von Elementen darstellen: z api/todo wird ein Array von Todos zurückgeben, daher sollten Sie es in api/todos umbenennen.