Aktivieren von CRUD-Vorgängen in ASP.NET-Web-API 1
von Mike Wasson
Abgeschlossenes Projekt herunterladen
In diesem Tutorial erfahren Sie, wie Sie CRUD-Vorgänge in einem HTTP-Dienst mithilfe von ASP.NET-Web-API für ASP.NET 4.x unterstützen.
Im Tutorial verwendete Softwareversionen
- Visual Studio 2012
- Web-API 1 (funktioniert auch mit Web-API 2)
CRUD steht für "Erstellen, Lesen, Aktualisieren und Löschen", bei denen es sich um die vier grundlegenden Datenbankvorgänge handelt. Viele HTTP-Dienste modellieren auch CRUD-Vorgänge über REST- oder REST-ähnliche APIs.
In diesem Tutorial erstellen Sie eine sehr einfache Web-API zum Verwalten einer Liste von Produkten. Jedes Produkt enthält einen Namen, einen Preis und eine Kategorie (z. B. "Spielzeug" oder "Hardware") sowie eine Produkt-ID.
Die Produkt-API macht die folgenden Methoden verfügbar.
Action | HTTP-Methode | Relativer URI |
---|---|---|
Abrufen einer Liste aller Produkte | GET | /api/products |
Abrufen eines Produkts nach ID | GET | /api/products/id |
Abrufen eines Produkts nach Kategorie | GET | /api/products?category=category |
Erstellen eines neuen Produkts | POST | /api/products |
Aktualisieren eines Produkts | PUT | /api/products/id |
Löschen eines Produkts | Delete | /api/products/id |
Beachten Sie, dass einige der URIs die Produkt-ID im Pfad enthalten. Um beispielsweise das Produkt mit der ID 28 abzurufen, sendet der Client eine GET-Anforderung für http://hostname/api/products/28
.
Ressourcen
Die Products-API definiert URIs für zwei Ressourcentypen:
Resource | URI |
---|---|
Die Liste aller Produkte. | /api/products |
Ein einzelnes Produkt. | /api/products/id |
Methoden
Die vier Standard HTTP-Methoden (GET, PUT, POST und DELETE) können CRUD-Vorgängen wie folgt zugeordnet werden:
- GET ruft die Darstellung der Ressource an einem angegebenen URI ab. GET sollte keine Nebenwirkungen auf dem Server haben.
- PUT aktualisiert eine Ressource an einem angegebenen URI. PUT kann auch verwendet werden, um eine neue Ressource an einem angegebenen URI zu erstellen, wenn der Server Clients das Angeben neuer URIs zulässt. In diesem Tutorial unterstützt die API die Erstellung über PUT nicht.
- POST erstellt eine neue Ressource. Der Server weist den URI für das neue Objekt zu und gibt diesen URI als Teil der Antwortnachricht zurück.
- DELETE löscht eine Ressource an einem angegebenen URI.
Hinweis: Die PUT-Methode ersetzt die gesamte Produktentität. Das heißt, vom Client wird erwartet, dass er eine vollständige Darstellung des aktualisierten Produkts sendet. Wenn Sie Teilupdates unterstützen möchten, wird die PATCH-Methode bevorzugt. In diesem Tutorial wird PATCH nicht implementiert.
Erstellen eines neuen Web-API-Projekts
Führen Sie zunächst Visual Studio aus, und wählen Sie neues Projektauf der Startseite aus. Oder wählen Sie im Menü Datei die Option Neu und dann Projekt aus.
Wählen Sie im Bereich Vorlagendie Option Installierte Vorlagen aus, und erweitern Sie den Knoten Visual C# . Wählen Sie unter Visual C#die Option Web aus. Wählen Sie in der Liste der Projektvorlagen ASP.NET MVC 4-Webanwendung aus. Nennen Sie das Projekt "ProductStore", und klicken Sie auf OK.
Wählen Sie im Dialogfeld Neues ASP.NET MVC 4-Projektdie Option Web-API aus, und klicken Sie auf OK.
Hinzufügen eines Modells
Ein Modell ist ein Objekt, das für die Daten in Ihrer Anwendung steht. In ASP.NET-Web-API können Sie stark typisierte CLR-Objekte als Modelle verwenden, die automatisch in XML oder JSON für den Client serialisiert werden.
Für die ProductStore-API bestehen unsere Daten aus Produkten, sodass wir eine neue Klasse mit dem Namen Product
erstellen.
Wenn der Projektmappen-Explorer nicht bereits sichtbar ist, können Sie auf das Menü Ansicht klicken und Projektmappen-Explorer wählen. Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Modelle. Wählen Sie im Kontextmenü Hinzufügen und dann Klasse aus. Nennen Sie die Klasse "Product".
Fügen Sie der -Klasse die Product
folgenden Eigenschaften hinzu.
namespace ProductStore.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
}
Hinzufügen eines Repositorys
Wir müssen eine Sammlung von Produkten speichern. Es ist eine gute Idee, die Sammlung von unserer Dienstimplementierung zu trennen. Auf diese Weise können wir den Sicherungsspeicher ändern, ohne die Dienstklasse neu zu schreiben. Dieser Typ von Entwurf wird als Repositorymuster bezeichnet. Definieren Sie zunächst eine generische Schnittstelle für das Repository.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Modelle. Wählen Sie Hinzufügen und dann Neues Element aus.
Wählen Sie im Bereich Vorlagendie Option Installierte Vorlagen aus, und erweitern Sie den Knoten C#. Wählen Sie unter C# die Option Code aus. Wählen Sie in der Liste der Codevorlagen die Option Schnittstelle aus. Nennen Sie die Schnittstelle "IProductRepository".
Fügen Sie die folgende Implementierung hinzu:
namespace ProductStore.Models
{
public interface IProductRepository
{
IEnumerable<Product> GetAll();
Product Get(int id);
Product Add(Product item);
void Remove(int id);
bool Update(Product item);
}
}
Fügen Sie nun dem Ordner Models eine weitere Klasse mit dem Namen "ProductRepository" hinzu. Diese Klasse implementiert die IProductRepository
-Schnittstelle. Fügen Sie die folgende Implementierung hinzu:
namespace ProductStore.Models
{
public class ProductRepository : IProductRepository
{
private List<Product> products = new List<Product>();
private int _nextId = 1;
public ProductRepository()
{
Add(new Product { Name = "Tomato soup", Category = "Groceries", Price = 1.39M });
Add(new Product { Name = "Yo-yo", Category = "Toys", Price = 3.75M });
Add(new Product { Name = "Hammer", Category = "Hardware", Price = 16.99M });
}
public IEnumerable<Product> GetAll()
{
return products;
}
public Product Get(int id)
{
return products.Find(p => p.Id == id);
}
public Product Add(Product item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
item.Id = _nextId++;
products.Add(item);
return item;
}
public void Remove(int id)
{
products.RemoveAll(p => p.Id == id);
}
public bool Update(Product item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
int index = products.FindIndex(p => p.Id == item.Id);
if (index == -1)
{
return false;
}
products.RemoveAt(index);
products.Add(item);
return true;
}
}
}
Das Repository speichert die Liste im lokalen Speicher. Dies ist für ein Tutorial in Ordnung, aber in einer echten Anwendung würden Sie die Daten extern speichern, entweder in einer Datenbank oder im Cloudspeicher. Das Repositorymuster erleichtert es, die Implementierung später zu ändern.
Hinzufügen eines Web-API-Controllers
Wenn Sie mit ASP.NET MVC gearbeitet haben, sind Sie bereits mit Controllern vertraut. In ASP.NET-Web-API ist ein Controller eine Klasse, die HTTP-Anforderungen vom Client verarbeitet. Der Assistent neues Projekt hat beim Erstellen des Projekts zwei Controller für Sie erstellt. Um sie anzuzeigen, erweitern Sie den Ordner Controller in Projektmappen-Explorer.
- HomeController ist ein herkömmlicher ASP.NET MVC-Controller. Sie ist für die Bereitstellung von HTML-Seiten für die Website verantwortlich und steht nicht in direktem Zusammenhang mit unserer Web-API.
- ValuesController ist ein WebAPI-Beispielcontroller.
Löschen Sie ValuesController, indem Sie mit der rechten Maustaste auf die Datei in Projektmappen-Explorer klicken und Löschen auswählen. Fügen Sie nun wie folgt einen neuen Controller hinzu:
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner „Controller“. Wählen Sie Hinzufügen und dann Controller.
Nennen Sie den Controller im Assistenten Zum Hinzufügen von Controllern den Namen "ProductsController". Wählen Sie in der Dropdownliste Vorlage die Option Leerer API-Controller aus. Klicken Sie anschließend auf Hinzufügen.
Hinweis
Es ist nicht erforderlich, Ihre Controller in einen Ordner namens Controller zu speichern. Der Ordnername ist nicht wichtig. Es ist einfach eine bequeme Möglichkeit, Ihre Quelldateien zu organisieren.
Der Assistent zum Hinzufügen von Controllern erstellt im Ordner Controller eine Datei namens ProductsController.cs. Doppelklicken Sie auf die Datei, um sie zu öffnen, falls sie noch nicht geöffnet ist. Fügen Sie die folgende using-Anweisung hinzu:
using ProductStore.Models;
Fügen Sie ein Feld hinzu, das eine IProductRepository-instance enthält.
public class ProductsController : ApiController
{
static readonly IProductRepository repository = new ProductRepository();
}
Hinweis
Das Aufrufen new ProductRepository()
des Controllers ist nicht der beste Entwurf, da er den Controller an eine bestimmte Implementierung von IProductRepository
bindet. Einen besseren Ansatz finden Sie unter Verwenden des Abhängigkeitslösers der Web-API.
Abrufen einer Ressource
Die ProductStore-API macht mehrere "Leseaktionen" als HTTP GET-Methoden verfügbar. Jede Aktion entspricht einer Methode in der ProductsController
-Klasse.
Action | HTTP-Methode | Relativer URI |
---|---|---|
Abrufen einer Liste aller Produkte | GET | /api/products |
Abrufen eines Produkts nach ID | GET | /api/products/id |
Abrufen eines Produkts nach Kategorie | GET | /api/products?category=category |
Um die Liste aller Produkte abzurufen, fügen Sie der ProductsController
-Klasse diese Methode hinzu:
public class ProductsController : ApiController
{
public IEnumerable<Product> GetAllProducts()
{
return repository.GetAll();
}
// ....
}
Der Methodenname beginnt mit "Get", sodass er gemäß der Konvention GET-Anforderungen zugeordnet wird. Da die Methode auch keine Parameter aufweist, wird sie einem URI zugeordnet, der kein "id"- Segment im Pfad enthält.
Um ein Produkt nach ID abzurufen, fügen Sie der ProductsController
-Klasse diese Methode hinzu:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Dieser Methodenname beginnt auch mit "Get", aber die Methode verfügt über einen Parameter namens id. Dieser Parameter wird dem "id"-Segment des URI-Pfads zugeordnet. Das ASP.NET-Web-API Framework konvertiert die ID automatisch in den richtigen Datentyp (int) für den Parameter.
Die GetProduct-Methode löst eine Ausnahme vom Typ HttpResponseException aus, wenn die ID ungültig ist. Diese Ausnahme wird vom Framework in einen Fehler 404 (Nicht gefunden) übersetzt.
Fügen Sie schließlich eine Methode hinzu, um Produkte nach Kategorie zu finden:
public IEnumerable<Product> GetProductsByCategory(string category)
{
return repository.GetAll().Where(
p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
}
Wenn der Anforderungs-URI über eine Abfragezeichenfolge verfügt, versucht die Web-API, die Abfrageparameter mit Parametern für die Controllermethode abzugleichen. Daher wird dieser Methode ein URI des Formulars "api/products?category=category" zugeordnet.
Erstellen einer Ressource
Als Nächstes fügen wir der ProductsController
-Klasse eine Methode hinzu, um ein neues Produkt zu erstellen. Hier sehen Sie eine einfache Implementierung der Methode:
// Not the final implementation!
public Product PostProduct(Product item)
{
item = repository.Add(item);
return item;
}
Beachten Sie zwei Dinge zu dieser Methode:
- Der Methodenname beginnt mit "Post...". Um ein neues Produkt zu erstellen, sendet der Client eine HTTP POST-Anforderung.
- Die -Methode nimmt einen Parameter vom Typ Product an. In der Web-API werden Parameter mit komplexen Typen aus dem Anforderungstext deserialisiert. Daher erwarten wir, dass der Client eine serialisierte Darstellung eines Produktobjekts im XML- oder JSON-Format sendet.
Diese Implementierung funktioniert, ist aber noch nicht ganz abgeschlossen. Idealerweise sollte die HTTP-Antwort Folgendes enthalten:
- Antwortcode: Standardmäßig legt das Web-API-Framework die Antwort status Code auf 200 (OK) fest. Gemäß dem HTTP/1.1-Protokoll sollte der Server jedoch mit status 201 (Erstellt) antworten, wenn eine POST-Anforderung zur Erstellung einer Ressource führt.
- Lage: Wenn der Server eine Ressource erstellt, sollte sie den URI der neuen Ressource im Location-Header der Antwort enthalten.
ASP.NET-Web-API erleichtert die Bearbeitung der HTTP-Antwortnachricht. Hier sehen Sie die verbesserte Implementierung:
public HttpResponseMessage PostProduct(Product item)
{
item = repository.Add(item);
var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
string uri = Url.Link("DefaultApi", new { id = item.Id });
response.Headers.Location = new Uri(uri);
return response;
}
Beachten Sie, dass der Methodenrückgabetyp jetzt HttpResponseMessage ist. Durch Zurückgeben einer HttpResponseMessage anstelle eines Product können wir die Details der HTTP-Antwortnachricht steuern, einschließlich des status-Codes und des Location-Headers.
Die CreateResponse-Methode erstellt eine HttpResponseMessage und schreibt automatisch eine serialisierte Darstellung des Product-Objekts in den Text der Antwortnachricht.
Hinweis
In diesem Beispiel wird nicht Product
überprüft. Informationen zur Modellüberprüfung finden Sie unter Modellvalidierung in ASP.NET-Web-API.
Aktualisieren einer Ressource
Das Aktualisieren eines Produkts mit PUT ist einfach:
public void PutProduct(int id, Product product)
{
product.Id = id;
if (!repository.Update(product))
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
Der Methodenname beginnt mit "Put...", sodass die Web-API ihn mit PUT-Anforderungen abgleicht. Die Methode benötigt zwei Parameter, die Produkt-ID und das aktualisierte Produkt. Der id-Parameter wird aus dem URI-Pfad entnommen, und der Product-Parameter wird aus dem Anforderungstext deserialisiert. Standardmäßig akzeptiert das ASP.NET-Web-API Framework einfache Parametertypen aus der Route und komplexe Typen aus dem Anforderungstext.
Löschen einer Ressource
Um eine Ressource zu löschen, definieren Sie "Löschen..." Methode.
public void DeleteProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
repository.Remove(id);
}
Wenn eine DELETE-Anforderung erfolgreich ist, kann sie status 200 (OK) mit einem Entitätstext zurückgeben, der die status beschreibt. status 202 (Akzeptiert), wenn der Löschvorgang noch aussteht; oder status 204 (Kein Inhalt) ohne Entitätstext. In diesem Fall verfügt die DeleteProduct
Methode über einen void
Rückgabetyp, sodass ASP.NET-Web-API dies automatisch in status Code 204 (No Content) übersetzt.