DEV Community 👩‍💻👨‍💻

Verónica Guamán
Verónica Guamán

Posted on • Updated on

API con ASP.NET MVC 6 y SQL Server mediante Entity Framework core 6 - Code First - Parte 2

En la Primera parte vimos la configuración de Entity Framework en nuestro proyecto, para poder conectarnos con SQL Server. Si ya tienes todo listo podemos continuar, si aún no la tienes puedes volver AQUÍ.

En esta segunda parte vamos a realizar los Métodos CRUD de nuestra API, En este caso vamos a trabajar con un repositorio, interfaz, controlador y finalmente probarlo mediante Swagger. Si bien podríamos hacerlo directamente en el controlador, no es recomendable tener los métodos tan expuestos. y en proyectos reales, lo realizamos en proyectos diferentes (Data, Services, API), en este tutorial lo simularemos en un solo proyecto.

Dicho esto, vamos a ello.

1. Crear la interfaz

Para esto, en nuestra carpeta Models vamos a crear una nueva carpeta llamada Repository, dentro de esta agregamos una interfaz que se llamará IProductRepository.
Aquí vamos a agregar los métodos que tendrá nuestro CRUD.

namespace DemoAPI.Models.Repository
{
    public interface IProductRepository
    {
        Task<Product> CreateProductAsync(Product product);
        Task<bool> DeleteProductAsync(Product product);
        Product GetProductById(int id);
        IEnumerable<Product> GetProducts();
        Task<bool> UpdateProductAsync(Product product);
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Crear el Repositorio

En la misma carpeta, Repository agregaremos una nueva clase y la llamaremos ProductRepository.
El siguiente paso será realizar la implementación de nuestra interfaz IProductRepository. Aquí vamos a realizar nuestro CRUD. En este archivo vamos a realizar la conexión a nuestra base de datos, así no lo tenemos expuesto directamente en nuestro controlador y se verá de la siguiente manera.

using Microsoft.EntityFrameworkCore;

namespace DemoAPI.Models.Repository
{
    public class ProductRepository : IProductRepository
    {
        protected readonly DemoContext _context;
        public ProductRepository(DemoContext context) => _context = context;

        public IEnumerable<Product> GetProducts()
        {
            return _context.Products.ToList();
        }

        public Product GetProductById(int id)
        {
            return _context.Products.Find(id);
        }
        public async Task<Product> CreateProductAsync(Product product)
        {
            await _context.Set<Product>().AddAsync(product);
            await _context.SaveChangesAsync();
            return product;
        }

        public async Task<bool> UpdateProductAsync(Product product)
        {
            _context.Entry(product).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeleteProductAsync(Product product)
        {
            //var entity = await GetByIdAsync(id);
            if (product is null)
            {
                return false;
            }
            _context.Set<Product>().Remove(product);
            await _context.SaveChangesAsync();

            return true;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Configurar Repository

Para poder usar nuestra interfaz tenemos que realizar la siguiente configuración en el archivo Program.cs, vamos a agregar las siguientes líneas debajo de la configuración de Entity Framework.

builder.Services.AddTransient<IProductRepository, ProductRepository>();
Enter fullscreen mode Exit fullscreen mode

4. Configurar el controlador

Ya tenemos todo listo para crear nuestro controlador.
En la Carpeta Controlador agregamos un nuevo controlador y lo llamaremos ProductController.
Vamos a crear la configuración para poder acceder desde la interfaz al repositorio y poder hacer la llamada a los métodos creados en esta clase.

private IProductRepository _productRepository;

        public ProductController(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }
Enter fullscreen mode Exit fullscreen mode

5. Crear los métodos en nuestro controlador

Como se trata de un API, mediante los verbos Http vamos a etiquetar cada método acorde a la acción que va a realizar, HttpGet para obtener Datos, HttpPost para hacer inserts, HttpPut para Editar datos existentes, y HttpDelete para eliminar.
Para crear los métodos de nuestro CRUD, mediante la interfaz llamamos a los métodos ya creados en el repositorio y enviamos los datos recibidos y nuestro controlador quedará de la siguiente forma.

using DemoAPI.Models;
using DemoAPI.Models.Repository;
using Microsoft.AspNetCore.Mvc;

namespace DemoAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        private IProductRepository _productRepository;

        public ProductController(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        [HttpGet]
        [ActionName(nameof(GetProductsAsync))]
        public IEnumerable<Product> GetProductsAsync()
        {
            return _productRepository.GetProducts();
        }

        [HttpGet("{id}")]
        [ActionName(nameof(GetProductById))]
        public ActionResult<Product> GetProductById(int id)
        {
            var productByID = _productRepository.GetProductById(id);
            if (productByID == null)
            {
                return NotFound();
            }
            return productByID;
        }

        [HttpPost]
        [ActionName(nameof(CreateProductAsync))]
        public async Task<ActionResult<Product>> CreateProductAsync(Product product)
        {
            await _productRepository.CreateProductAsync(product);
            return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product);
        }

        [HttpPut("{id}")]
        [ActionName(nameof(UpdateProduct))]
        public async Task<ActionResult> UpdateProduct(int id, Product product)
        {
            if (id != product.Id)
            {
                return BadRequest();
            }

            await _productRepository.UpdateProductAsync(product);

            return NoContent();

        }

        [HttpDelete("{id}")]
        [ActionName(nameof(DeleteProduct))]
        public async Task<IActionResult> DeleteProduct(int id)
        {
            var product = _productRepository.GetProductById(id);
            if (product == null)
            {
                return NotFound();
            }

            await _productRepository.DeleteProductAsync(product);

            return NoContent();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Finalmente vamos a ejecutar nuestra Aplicación y vamos a probar que todo funcione correctamente.
Por defecto al crearse el proyecto, nuestra API viene integrada con Swagger, que es una OPEN API para documentación y viene integrada con una interfaz que nos permite probar nuestros métodos. (Si deseas saber más de Swagger te dejo el siguiente artículo)

Image description

Primero vamos a probar nuestro método Post, ingresando un producto, en este caso simularemos el ingreso de un teclado.
Image description

Al darle a Execute tiene que darnos una respuesta, en este caso el código 200 para indicarnos que todo está correcto.

Image description

Finalmente vamos a probar nuestro Get y verificar que nuestro insertar funciono correctamente.

Image description
Y así hemos completado nuestra API.

Muchas gracias por leerme y Nos vemos en Twitter e Instagram ;)

Top comments (4)

Collapse
hugofajardo1 profile image
HugoFajardo1

Hola. Sigo tus indicaciones, y al ejecutar el HttpPost tira un error. Se debe a que la columna Id en la tabla Product es autoincrementable. Si a ese campo de la tabla le saco el autoincremento funciona, pero la idea es que la base de datos gestione la clave primaria. Como puedo solucionarlo?

Saludos

Hugo Fajardo

Collapse
veronicaguamann profile image
Verónica Guamán Author

Hola Hugo muchas gracias por seguir el tutorial.
Nose si entiendo bien, pero ¿deseas que el ID sea auto incrementable?

Collapse
hugofajardo1 profile image
HugoFajardo1

Si, eso quiero.

Thread Thread
veronicaguamann profile image
Verónica Guamán Author

En teoría con la etiqueta [Key] en el atributo del ID debería funcionar pero podemos ayudarnos de la etiqueta
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] debajo de [Key] y arriba del atributo.
Puedes probarle eso porfis y me comentas

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.