Parte 3: Creazione di un controller di Amministrazione
di Rick Anderson
Scaricare il progetto completato
Aggiungere un controller Amministrazione
In questa sezione verrà aggiunto un controller API Web che supporta operazioni CRUD (creazione, lettura, aggiornamento ed eliminazione) sui prodotti. Il controller userà Entity Framework per comunicare con il livello del database. Solo gli amministratori potranno usare questo controller. I clienti accederanno ai prodotti tramite un altro controller.
In Esplora soluzioni fare clic sulla cartella Controller. Selezionare Aggiungi e quindi Controller.
Nella finestra di dialogo Aggiungi controller assegnare al controller AdminController
il nome . In Modello selezionare "Controller API con azioni di lettura/scrittura, usando Entity Framework". In Classe modello selezionare "Product (ProductStore.Models)". In Contesto dati selezionare "<Nuovo contesto> dati".
Nota
Se l'elenco a discesa Classe modello non mostra alcuna classe di modello, assicurarsi di compilare il progetto. Entity Framework usa la reflection, quindi richiede l'assembly compilato.
Se si seleziona "<Nuovo contesto> dati", verrà aperta la finestra di dialogo Nuovo contesto dati . Assegnare al contesto ProductStore.Models.OrdersContext
dati il nome .
Fare clic su OK per chiudere la finestra di dialogo Nuovo contesto dati . Nella finestra di dialogo Aggiungi controller fare clic su Aggiungi.
Ecco cosa è stato aggiunto al progetto:
- Classe denominata
OrdersContext
che deriva da DbContext. Questa classe fornisce l'associazione tra i modelli POCO e il database. - Un controller API Web denominato
AdminController
. Questo controller supporta operazioni CRUD sulleProduct
istanze di . Usa laOrdersContext
classe per comunicare con Entity Framework. - Nuova stringa di connessione del database nel file Web.config.
Aprire il file OrdersContext.cs. Si noti che il costruttore specifica il nome della stringa di connessione del database. Questo nome fa riferimento alla stringa di connessione aggiunta a Web.config.
public OrdersContext() : base("name=OrdersContext")
Aggiungere le proprietà seguenti alla classe OrdersContext
:
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
Un oggetto DbSet rappresenta un set di entità su cui è possibile eseguire query. Ecco l'elenco completo per la OrdersContext
classe:
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; }
}
La AdminController
classe definisce cinque metodi che implementano la funzionalità CRUD di base. Ogni metodo corrisponde a un URI che il client può richiamare:
Metodo controller | Descrizione | URI | Metodo HTTP |
---|---|---|---|
GetProducts | Ottiene tutti i prodotti. | api/products | GET |
GetProduct | Trova un prodotto in base all'ID. | api/products/id | GET |
PutProduct | Aggiornamenti un prodotto. | api/products/id | PUT |
PostProduct | Crea un nuovo prodotto. | api/products | POST |
DeleteProduct | Elimina un prodotto. | api/products/id | DELETE |
Ogni metodo chiama in OrdersContext
per eseguire una query sul database. I metodi che modificano la raccolta (PUT, POST e DELETE) chiamano db.SaveChanges
per rendere persistenti le modifiche apportate al database. I controller vengono creati per richiesta HTTP e quindi eliminati, quindi è necessario rendere persistenti le modifiche prima che venga restituito un metodo.
Aggiungere un inizializzatore di database
Entity Framework offre una funzionalità utile che consente di popolare il database all'avvio e ricreare automaticamente il database ogni volta che i modelli cambiano. Questa funzionalità è utile durante lo sviluppo, perché sono sempre disponibili alcuni dati di test, anche se si modificano i modelli.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Models e creare una nuova classe denominata OrdersContextInitializer
. Incollare l'implementazione seguente:
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();
}
}
}
Ereditando dalla classe DropCreateDatabaseIfModelChanges , si indica a Entity Framework di eliminare il database ogni volta che si modificano le classi del modello. Quando Entity Framework crea o ricrea il database, chiama il metodo Seed per popolare le tabelle. Viene usato il metodo Seed per aggiungere alcuni prodotti di esempio e un ordine di esempio.
Questa funzionalità è ideale per i test, ma non usare la classe DropCreateDatabaseIfModelChanges nell'ambiente di produzione, perché è possibile perdere i dati se un utente modifica una classe di modello.
Aprire quindi Global.asax e aggiungere il codice seguente al metodo Application_Start :
System.Data.Entity.Database.SetInitializer(
new ProductStore.Models.OrdersContextInitializer());
Inviare una richiesta al controller
A questo punto, non è stato scritto alcun codice client, ma è possibile richiamare l'API Web usando un Web browser o uno strumento di debug HTTP, ad esempio Fiddler. In Visual Studio premere F5 per avviare il debug. Il Web browser si aprirà a http://localhost:*portnum*/
, dove portnum è un numero di porta.
Inviare una richiesta HTTP a "http://localhost:*portnum*/api/admin
. La prima richiesta può essere lenta da completare, perché Entity Framework deve creare ed eseguire il seeding del database. La risposta dovrebbe essere simile alla seguente:
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}]