Část 3: Vytvoření kontroleru Správa
Rick Anderson
Přidání kontroleru Správa
V této části přidáme kontroler webového rozhraní API, který podporuje operace CRUD (vytvoření, čtení, aktualizace a odstranění) u produktů. Kontroler bude ke komunikaci s vrstvou databáze používat Entity Framework. Tento kontroler budou moct používat jenom správci. Zákazníci budou k produktům přistupovat prostřednictvím jiného kontroleru.
V Průzkumník řešení klikněte pravým tlačítkem na složku Kontrolery. Vyberte Přidat a pak Kontroler.
V dialogovém okně Přidat kontroler pojmenujte kontroler AdminController
. V části Šablona vyberte Kontroler rozhraní API s akcemi čtení a zápisu pomocí Entity Frameworku. V části Třída modelu vyberte Product (ProductStore.Models). V části Kontext dat vyberte Nový< kontext> dat.
Poznámka
Pokud rozevírací seznam Třída modelu nezobrazuje žádné třídy modelu, ujistěte se, že jste projekt zkompilovali. Entity Framework používá reflexi, takže potřebuje zkompilované sestavení.
Výběrem možnosti< Nový kontext> dat se otevře dialogové okno Nový kontext dat . Pojmenujte kontext ProductStore.Models.OrdersContext
dat .
Kliknutím na OK zavřete dialogové okno Nový kontext dat . V dialogovém okně Přidat kontroler klikněte na Přidat.
Tady je, co se přidalo do projektu:
- Třída s názvem
OrdersContext
, která je odvozena z DbContext. Tato třída poskytuje spojení mezi modely POCO a databází. - Kontroler webového rozhraní API s názvem
AdminController
. Tento kontroler podporuje operace CRUD vProduct
instancích. PoužíváOrdersContext
třídu ke komunikaci s Entity Framework. - Nový připojovací řetězec databáze v souboru Web.config.
Otevřete soubor OrdersContext.cs. Všimněte si, že konstruktor určuje název připojovacího řetězce databáze. Tento název odkazuje na připojovací řetězec přidaný do Web.config.
public OrdersContext() : base("name=OrdersContext")
Přidejte do OrdersContext
třídy následující vlastnosti:
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
DbSet představuje sadu entit, které lze dotazovat. Tady je úplný výpis pro OrdersContext
třídu:
public class OrdersContext : DbContext
{
public OrdersContext() : base("name=OrdersContext")
{
}
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
public DbSet<Product> Products { get; set; }
}
Třída AdminController
definuje pět metod, které implementují základní funkce CRUD. Každá metoda odpovídá identifikátoru URI, který může klient vyvolat:
Controller – metoda | Description | Identifikátor URI | Metoda HTTP |
---|---|---|---|
GetProducts | Získá všechny produkty. | api/products | GET |
GetProduct | Vyhledá produkt podle ID. | api/products/id | GET |
PutProduct | Aktualizace produktu. | api/products/id | PUT |
PostProduct | Vytvoří nový produkt. | api/products | POST |
DeleteProduct | Odstraní produkt. | api/products/id | DELETE |
Každá metoda volá do OrdersContext
a dotazuje databázi. Metody, které upravují kolekci (PUT, POST a DELETE), volají db.SaveChanges
k zachování změn v databázi. Kontrolery se vytvoří na základě požadavku HTTP a pak se zlikvidují, takže před vrácením metody je nutné zachovat změny.
Přidání inicializátoru databáze
Entity Framework má pěknou funkci, která umožňuje naplnit databázi při spuštění a automaticky znovu vytvořit databázi při každé změně modelů. Tato funkce je užitečná při vývoji, protože vždy máte nějaká testovací data, i když změníte modely.
V Průzkumník řešení klikněte pravým tlačítkem na složku Models (Modely) a vytvořte novou třídu s názvem OrdersContextInitializer
. Vložte následující implementaci:
namespace ProductStore.Models
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
public class OrdersContextInitializer : DropCreateDatabaseIfModelChanges<OrdersContext>
{
protected override void Seed(OrdersContext context)
{
var products = new List<Product>()
{
new Product() { Name = "Tomato Soup", Price = 1.39M, ActualCost = .99M },
new Product() { Name = "Hammer", Price = 16.99M, ActualCost = 10 },
new Product() { Name = "Yo yo", Price = 6.99M, ActualCost = 2.05M }
};
products.ForEach(p => context.Products.Add(p));
context.SaveChanges();
var order = new Order() { Customer = "Bob" };
var od = new List<OrderDetail>()
{
new OrderDetail() { Product = products[0], Quantity = 2, Order = order},
new OrderDetail() { Product = products[1], Quantity = 4, Order = order }
};
context.Orders.Add(order);
od.ForEach(o => context.OrderDetails.Add(o));
context.SaveChanges();
}
}
}
Děděním z DropCreateDatabaseIfModelChanges třídy, říkáme Entity Framework, aby při každé úpravě tříd modelu vyřadila databázi. Když Entity Framework vytvoří (nebo znovu vytvoří) databázi, zavolá metodu Seed k naplnění tabulek. K přidání některých ukázkových produktů a ukázkové objednávky používáme metodu Seed .
Tato funkce je skvělá pro testování, ale nepoužívejte třídu DropCreateDatabaseIfModelChanges v produkčním prostředí, protože pokud někdo změní třídu modelu, může dojít ke ztrátě dat.
Dále otevřete Global.asax a do metody Application_Start přidejte následující kód:
System.Data.Entity.Database.SetInitializer(
new ProductStore.Models.OrdersContextInitializer());
Odeslání žádosti kontroleru
V tuto chvíli jsme nenapsali žádný klientský kód, ale webové rozhraní API můžete vyvolat pomocí webového prohlížeče nebo ladicího nástroje HTTP, jako je Fiddler. V sadě Visual Studio spusťte ladění stisknutím klávesy F5. Ve webovém prohlížeči se otevře http://localhost:*portnum*/
parametr , kde portnum je nějaké číslo portu.
Odešlete požadavek HTTP na adresu .http://localhost:*portnum*/api/admin
Dokončení prvního požadavku může být pomalé, protože Entity Framework potřebuje vytvořit a dosadí databázi. Odpověď by měla vypadat nějak takto:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 18 Jun 2012 04:30:33 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 175
Connection: Close
[{"Id":1,"Name":"Tomato Soup","Price":1.39,"ActualCost":0.99},{"Id":2,"Name":"Hammer",
"Price":16.99,"ActualCost":10.00},{"Id":3,"Name":"Yo yo","Price":6.99,"ActualCost":
2.05}]