# 5.4 Creando el servicio Productos

### Creando el controlador para los productos

Creamos nuestro servicio para los productos.

1. Da clic con el botón derecho de mouse sobre la carpeta Controller. Luego da clic en **Agregar -> Nuevo elemento con scaffold...**
2. &#x20;Seleccionamos la opción **Controlador de API con acciones que usan Entity Framework** y damos clic en el botón **Agregar**
3. En Clase de Modelo seleccionamos nuestra clase **Producto.**
4. El nombre del controlador le llamamos **ProductosController** y damos clic en **Agregar**

### Creando la clase de acceso a Datos para los productos

Creamos nuestra clase **ProductoDAO** en nuestra carpeta **DAO,** puedes copiar el código de tu clase CategoriaDAO y con la opción **Buscar y Remplazar** puedes remplazar la palabra categoria por Producto. O puedes copiar el código generado en cada método del controlador a tu clase ProductoDAO

{% code title="ProductoDAO.cs" %}

```csharp
public class ProductoDAO
{
    private readonly CaducaContext contexto;
    private readonly LocService localizacion;
    
    /// <summary>
    /// Mensaje de error personalizado
    /// </summary>
    public CustomError customError;

    /// <summary>
    /// Clase para acceso a la base de datos
    /// </summary>
    /// <param name="context"></param>
    public ProductoDAO(CaducaContext context, LocService locService)
    {
        this.contexto = context;
        this.localizacion = locService;
    }

    /// <summary>
    /// Obtiene todas las Productos
    /// </summary>
    /// <returns></returns>
    public List<Producto> ObtenerTodo()
    {
        return contexto.Producto.ToList();
    }

    /// <summary>
    /// Obtiene una Producto por us Id
    /// </summary>
    /// <param name="id">Id de la Producto</param>
    /// <returns></returns>
    public async Task<Producto> ObtenerPorIdAsync(int id)
    {
        return await contexto.Producto.FindAsync(id);
    }

    /// <summary>
    /// Permite agregar una nueva Producto
    /// </summary>
    /// <param name="Producto"></param>
    /// <returns></returns>
    public async Task<bool> AgregarAsync(Producto Producto)
    {
        Producto registroRepetido;
        try
        {
            registroRepetido = contexto.Producto.
                  FirstOrDefault(c => c.Nombre == Producto.Nombre);
            if (registroRepetido != null)
            {
                 customError = new CustomError(400, 
                         String.Format(this.localizacion
                             .GetLocalizedHtmlString("Repeteaded"), 
                                           "Producto",
                                           "nombre"), "Nombre");
                 return false;
            }
            registroRepetido = contexto.Producto.
                    FirstOrDefault(c => c.Clave == Producto.Clave);
            if (registroRepetido != null)
            {
                 customError = new CustomError(400, 
                         String.Format(this.localizacion
                             .GetLocalizedHtmlString("Repeteaded"), 
                                         "Producto", 
                                         "clave"), "Clave");
                 return false;
            }

            contexto.Producto.Add(Producto);
            await contexto.SaveChangesAsync();
        }
        catch (Exception ex)
        {
                Console.WriteLine(ex.Message);
                return false;
        }
        return true;
    }

    /// <summary>
    /// Modidica una Producto
    /// </summary>
    /// <param name="Producto">Datos de la Producto</param>
    /// <returns></returns>
    public async Task<bool> ModificarAsync(Producto Producto)
    {
        Producto registroRepetido;
        try
        {
            //Se busca si existe una Producto con el mismo nombre 
            //pero diferente Id
            registroRepetido = contexto.Producto
                            .FirstOrDefault(
                                   c => c.Nombre == Producto.Nombre
                                   && c.Id != Producto.Id);
            if (registroRepetido != null)
            {
               customError = new CustomError(400, 
                        String.Format(this.localizacion
                            .GetLocalizedHtmlString("Repeteaded"), 
                                    "Producto", "nombre"), "Nombre");
               return false;
             }
             registroRepetido = contexto.Producto
                         .FirstOrDefault(
                             c => c.Clave == Producto.Clave
                             && c.Id != Producto.Id);
             if (registroRepetido != null)
             {
                 customError = new CustomError(400, 
                            String.Format(this.localizacion
                                .GetLocalizedHtmlString("Repeteaded"),
                                    "Producto", "clave"), "Clave");
                 return false;
              }
              contexto.Entry(Producto).State = EntityState.Modified;
              await contexto.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ExisteProducto(Producto.Id))
            {
                 return false;
            }
        }
        return true;
    }

    /// <summary>
    /// Permite borrar una Producto por Id
    /// </summary>
    /// <param name="id">Id de la Producto</param>
    /// <returns></returns>
    public async Task<bool> BorraAsync(int id)
    {
        var Producto = await ObtenerPorIdAsync(id);
        if (Producto == null)
        {
            customError = new CustomError(404, 
                String.Format(this.localizacion
                    .GetLocalizedHtmlString("NotFound"), 
                                            "El Producto"), "Id");
            return false;
        }

        contexto.Producto.Remove(Producto);
        await contexto.SaveChangesAsync();
        return true;
    }

    private bool ExisteProducto(int id)
    {
        return contexto.Producto.Any(e => e.Id == id);
    }
}
```

{% endcode %}

### Modificando el controller

Modificamos nuestra clase controller para que reciba como parámetro el objeto LocService y que tome nuestra clase ProductoDAO

{% code title="ProductosController.cs" %}

```csharp
/// <summary>
/// Servicios para los productos
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class ProductosController : ControllerBase
{
	private readonly LocService _localizer;
	private readonly CaducaContext _context;
	private ProductoDAO productoDAO;
	/// <summary>
	/// Constructor
	/// </summary>
	/// <param name="context"></param>
	/// <param name="localize"></param>
	public ProductosController(CaducaContext context, 
	                           LocService localize)
	{
		_context = context;
		productoDAO = new ProductoDAO(context, localize);
	}

	/// <summary>
	/// Obtener todos los productos
	/// </summary>
	/// <returns></returns>
	// GET: api/Productos
	[HttpGet]
	public IEnumerable<Producto> GetProducto()
	{
		return productoDAO.ObtenerTodo();
	}

	/// <summary>
	/// Obtener un producto por su Id
	/// </summary>
	/// <param name="id"></param>
	/// <returns></returns>
	// GET: api/Productos/5
	[HttpGet("{id}")]
	public async Task<IActionResult> GetProducto([FromRoute] int id)
	{
		var producto = await productoDAO.ObtenerPorIdAsync(id);

		if (producto == null)
		{
			return NotFound();
		}

		return Ok(producto);
	}

	/// <summary>
	/// Actualizar un producto
	/// </summary>
	/// <param name="id">Id del producto</param>
	/// <param name="producto">Datos del producto</param>
	/// <returns></returns>
	// PUT: api/Productos/5
	[HttpPut("{id}")]
	public async Task<IActionResult> PutProducto([FromRoute] int id,
	                                  [FromBody] Producto producto)
	{
		if (!ModelState.IsValid)
		{
			return BadRequest(ModelState);
		}

		if (id != producto.Id)
		{
			return BadRequest();
		}

		if (!await productoDAO.ModificarAsync(producto))
		{
			return StatusCode(productoDAO.customError.StatusCode,
							  productoDAO.customError.Message);
		}

		return NoContent();

	}

	/// <summary>
	/// Agregar un producto
	/// </summary>
	/// <param name="producto">Datos del producto a agregar</param>
	/// <returns></returns>
	// POST: api/Productos
	[HttpPost]
	public async Task<IActionResult> PostProducto(
	              [FromBody] Producto producto)
	{
		if (!await productoDAO.AgregarAsync(producto))
		{
			return StatusCode(productoDAO.customError.StatusCode,
							  productoDAO.customError.Message);
		}

		return CreatedAtAction("GetProducto", 
		       new { id = producto.Id }, producto);
	}

	/// <summary>
	/// Borrar un producto
	/// </summary>
	/// <param name="id"></param>
	/// <returns></returns>
	// DELETE: api/Productos/5
	[HttpDelete("{id}")]
	public async Task<IActionResult> DeleteProducto(
	                                            [FromRoute] int id)
	{
		if (!ModelState.IsValid)
		{
			return BadRequest(ModelState);
		}
		if (!await productoDAO.BorraAsync(id))
		{
			return StatusCode(productoDAO.customError.StatusCode,
							  productoDAO.customError.Message);
		}
		return Ok();
	}

}
```

{% endcode %}
