Parte 3: Crear un controlador de administración
Por Rick Anderson
Descargar el proyecto completado
Adición de un controlador de administración
En esta sección, agregaremos un controlador de API web que admita operaciones CRUD (crear, leer, actualizar y eliminar) en productos. El controlador usará Entity Framework para comunicarse con la capa de base de datos. Solo los administradores podrán usar este controlador. Los clientes accederán a los productos a través de otro controlador.
En el Explorador de soluciones, haga clic con el botón derecho en la carpeta Controllers. Seleccione Agregar y, a continuación, Controlador.
En el cuadro de diálogo Agregar controlador, asigne al controlador el nombre AdminController
. En Plantilla, seleccione "Controlador de la API con acciones de lectura y escritura, que usa Entity Framework". En Clase modelo, seleccione "Producto (ProductStore.Models)". En Contexto de datos, seleccione "<Nuevo contexto de datos>".
Nota:
Si la lista desplegable Clase modelo no muestra ninguna clase de modelo, asegúrese de compilar el proyecto. Entity Framework usa la reflexión, por lo que necesita el ensamblado compilado.
Al seleccionar "<Nuevo contexto de datos>" se abrirá el cuadro de diálogo Nuevo contexto de datos. Asigne al contexto de datos el nombre ProductStore.Models.OrdersContext
.
Haga clic en Aceptar para descartar el cuadro de diálogo Nuevo contexto de datos. En el cuadro de diálogo Agregar controlador, haga clic en Agregar.
Esto es lo que se ha agregado al proyecto:
- Una clase denominada
OrdersContext
que se deriva de DbContext. Esta clase proporciona el pegamento entre los modelos POCO y la base de datos. - Un controlador de API web denominado
AdminController
. Este controlador admite operaciones CRUD en instanciasProduct
. Usa la claseOrdersContext
para comunicarse con Entity Framework. - Una nueva cadena de conexión de base de datos en el archivo Web.config.
Abra el archivo OrdersContext.cs. Observe que el constructor especifica el nombre de la cadena de conexión de base de datos. Este nombre hace referencia a la cadena de conexión que se agregó a Web.config.
public OrdersContext() : base("name=OrdersContext")
Agregue las propiedades siguientes a la clase OrdersContext
:
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
DbSet representa un conjunto de entidades que se pueden consultar. Esta es la lista completa de la clase OrdersContext
:
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 clase AdminController
define cinco métodos que implementan la funcionalidad CRUD básica. Cada método corresponde a un URI que el cliente puede invocar:
Método de controlador | Descripción | URI | Método de HTTP |
---|---|---|---|
GetProducts | Obtiene todos los productos. | api/products | OBTENER |
GetProduct | Busca un producto por identificador. | api/products/id | OBTENER |
PutProduct | Actualiza un producto. | api/products/id | PUT |
PostProduct | Crea un producto nuevo. | api/products | PUBLICAR |
DeleteProduct | Elimina un producto. | api/products/id | Delete |
Cada método llama a OrdersContext
para consultar la base de datos. Los métodos que modifican la colección (PUT, POST y DELETE) llaman a db.SaveChanges
para conservar los cambios en la base de datos. Los controladores se crean por solicitud HTTP y, a continuación, se eliminan, por lo que es necesario conservar los cambios antes de que un método haga la devolución.
Adición de un inicializador de base de datos
Entity Framework tiene una práctica característica que le permite rellenar la base de datos al iniciarse y volver a crear automáticamente la base de datos cada vez que cambien los modelos. Esta característica es útil durante el desarrollo, ya que siempre tiene algunos datos de prueba, incluso si cambia los modelos.
En el Explorador de soluciones, haga clic con el botón derecho en la carpeta Modelos y cree una nueva clase denominada OrdersContextInitializer
. Pegue la siguiente implementación:
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();
}
}
}
Al heredar de la clase DropCreateDatabaseIfModelChanges, se indica a Entity Framework que quite la base de datos cada vez que modifiquemos las clases de modelo. Cuando Entity Framework crea (o vuelve a crear) la base de datos, llama al método Seed para rellenar las tablas. Usamos el método Seed para agregar algunos productos de ejemplo más un pedido de ejemplo.
Esta característica es excelente para las pruebas, pero no usa la clase DropCreateDatabaseIfModelChanges en producción, ya que podría perder los datos si alguien cambia una clase de modelo.
A continuación, abra Global.asax y agregue el código siguiente al método Application_Start:
System.Data.Entity.Database.SetInitializer(
new ProductStore.Models.OrdersContextInitializer());
Envío de una solicitud al controlador
En este momento, no hemos escrito ningún código de cliente, pero puede invocar la API web mediante un explorador web o una herramienta de depuración HTTP como Fiddler. En Visual Studio, presione F5 para iniciar la depuración. El explorador web se abrirá en http://localhost:*portnum*/
, donde portnum es un número de puerto.
Envíe una solicitud HTTP a "http://localhost:*portnum*/api/admin
". La primera solicitud puede tardar en completarse, porque Entity Framework necesita crear e inicializar la base de datos. La respuesta debe ser similar a la siguiente:
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}]