Creando controladores
Clase 20 de 22 • Curso de APIs con .NET
Contenido del curso
Clase 20 de 22 • Curso de APIs con .NET
Contenido del curso
Felipe de Jesús Isidro
Wilson Bienvenido Otaño Mateo
rafael malanco velazquez
Erick Alexander Cabrera González
Diego Eduardo Téllez Contreras
JUAN PABLO MAYORGA MENDIETA
Boris Vargas Paucara
Felipe Ignacio Inostroza Vega
Edgar Alexander Espinoza Gonzalez
Miguel Teheran
Daniel Valencia Alvarez
Ronny Manuel De La Cruz Perez
Miguel Teheran
Juan Betancur
Carina Correjidor
Miguel Teheran
Jaime Eduardo Falla Cardozo
JUAN SEBASTIAN ORTIZ
Charly Johan Manrique Gómez
Miguel Teheran
Charly Johan Manrique Gómez
Juan Pablo Arano
Miguel Teheran
Edgar Alexander Espinoza Gonzalez
Miguel Teheran
Esteban Sánchez Ruiz
David Cubides Enciso
Enrique Arce Alejandro
Miguel Teheran
Alvaro Rafael Guete Puello
Jonathan Harley Sabogal toro
Rosmary Alejandra Rojas Perez
Miguel Teheran
Fernando Vergel
Miguel Teheran
Fernando Vergel
Luis Antonio Preza Padilla
Miguel Angel Reyes Moreno
Como recomendación la propiedad del servicio debería ser declarada como protected y de solo lectura de la siguiente forma
protected readonly ITareasService _tareasService;
es un estándar que recomienda .Net
Muchisimas gracias por ese aporte, vi que gpt lo uso una vez que se lo pedi, pero no sabia muchas gracias
Hola, para quienes al momento de compilar el codigo se les presenta el error:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor ‘ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService’: Unable to resolve service for type ‘webapi.TareasContext’ while attempting to activate ‘webapi.Services.CategoriaService’.) —> System.InvalidOperationException: Error while validating the service descriptor ‘ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService’: Unable to resolve service for type ‘webapi.TareasContext’ while attempting to activate ‘webapi.Services.CategoriaService’.
No es un error en el codigo en realidad, ya que al momento de seguir las clases siguientes y agregar el codigo que falta este "error" se soluciona. Muy segurmente no funciona por la falta de codigo adicional
Efectivamente es normal que aparezca eso, falta configurar otras cositas en la siguiente clase! Este comentario debería estar más arriba!
excelente, muchas gracias!
CategoriaController
using Microsoft.AspNetCore.Mvc; using webapi.Models; using webapi.Services; namespace webapi.Controllers; [Route("api/[controller]")] public class CategoriaController : ControllerBase { ICategoriaService categoriaService; public CategoriaController(ICategoriaService service) { categoriaService = service; } [HttpGet] public IActionResult Get() { return Ok(categoriaService.Get()); } [HttpPost] public IActionResult Post([FromBody] Categoria categoria) { categoriaService.Save(categoria); return Ok(); } [HttpPut("{id}")] public IActionResult Put(Guid id, [FromBody] Categoria categoria) { categoriaService.Update(id, categoria); return Ok(); } [HttpDelete("{id}")] public IActionResult Delete(Guid id) { categoriaService.Delete(id); return Ok(); } }
TareaController
using Microsoft.AspNetCore.Mvc; using webapi.Models; using webapi.Services; namespace webapi.Controllers; [Route("api/[controller]")] public class TareaController : ControllerBase { ITareaService tareaService; public TareaController(ITareaService service) { tareaService = service; } [HttpGet] public IActionResult Get() { return Ok(tareaService.Get()); } [HttpPost] public IActionResult Post([FromBody] Tarea tarea) { tareaService.Save(tarea); return Ok(); } [HttpPut("{id}")] public IActionResult Put(Guid id, [FromBody] Tarea tarea) { tareaService.Update(id, tarea); return Ok(); } [HttpDelete("{id}")] public IActionResult Delete(Guid id) { tareaService.Delete(id); return Ok(); } }
Gracias por el aporte! :D
porque no creamos como async los metodos en esta seccion, en teoria ese deberia ser el estandar o estoy errado?
Es una excelente practica usar async, mejora mucho el rendimiento
¿Es valido configurar todos los métodos (Get(), Post(), Put() y Delete()) como async o hay algúno que no deba tener esta configuración?
Al crear lo controladores de esta manera, como puedo consumirlos para pasarlo a la vista?
Debe cambiar el atributo de ApiController a Controller y puedes retornar la View indicando el nombre o ruta + nombre. Ejemplo "Views/Tareas/Index.cshtml" Mas info por acá: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/overview?view=aspnetcore-6.0
Miguel donde puedo encontrar el atributo ApiController?
Hola una consulta desde un controlador puedo generar un redirect ? como lo definiria?
Claro que si: return RedirectToRoute(new { controller = "User", action = "get" }); }
Faltó explicar en el curso los niveles en una Api REST
using Microsoft.AspNetCore.Mvc;
using webapi.Models;
using webapi.Services;
namespace webapi.Controllers;
[Route("api/[controller]")]
public class TareaController : ControllerBase
{
private readonly ITareaService TareaService;
public TareaController(ITareaService service)
{
TareaService = service;
}
[HttpGet]
public IActionResult Get()
{
var tareas = TareaService.Get();
return Ok(tareas);
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] Tarea tarea)
{
await TareaService.Save(tarea);
return Ok();
}
[HttpPut("{id}")]
public async Task<IActionResult> Put(Guid id, [FromBody] Tarea tarea)
{
await TareaService.Update(id, tarea);
return Ok();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(Guid id)
{
await TareaService.Delete(id);
return Ok();
}
}
buen día, de casualidad a alguno le funcionó el metodo put de la categoria ?
he intentado de varias maneras pero no me funciona, inclusive agregue el FromRoute pensando que llegara hacer eso, en postman lo pongo con comillas dobles,simples,sin comillas pero me sigue saliendo (404) recurso no encontrado, con el servicio de post y get si me funciona correctamente.
POSTMAN: https://localhost:7044/api/Categoria/Put/"fe2de405-c38e-4c90-ac52-da0540dfb402"
SERVICIO: public async Task Update(Guid id, Categoria categoria) { var categoriaActual = context.Categorias.Find(id);
if(categoriaActual != null) { categoriaActual.Nombre = categoria.Nombre; categoria.Descripcion = categoria.Descripcion; categoria.Peso = categoria.Peso; await context.SaveChangesAsync(); } }
CONTROLADOR
[HttpPut("{id}")] [Route("{action}")] public IActionResult Put([FromRoute]Guid id, [FromBody] Categoria categoria) { categoriaService.Update(id, categoria); return Ok(); }
Elimina el atributo route, por otro lado manda el ID sin commillas y no le coloques Put simplemente llamalo de esta manera por el http verb put en postman: https://localhost:7044/api/Categoria/fe2de405-c38e-4c90-ac52-da0540dfb402
Genial, me funciono correctamente muchas gracias.
A diferencia tuya, cuando te saltan errores de que no importaste una libreria, a mi me marca error pero no me dice que libreria deberia importar. Como puedo solucionarlo? Alguna extension?
debes instalar la extensión de C#, aveces igual toca esperar un rato a que la encuentre o reiniciar el Visual Code, para C# aveces salen estos problemas
porque en esta seccion no creamos los metodos como async tengo entendido que es el estandar o estoy errado?
Es una buena práctica hacerlos con Async ayuda mucho el performance
Excelente buena explicacion como siempre!
Bien explicado.
Me sale el siguiente error, y tengo la interface heredada "public class CategoriaService : ICategoriaService", el error es este:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.CategoriaService'.) ---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.CategoriaService'.
Segun error no tiene configurado correctamente el contexto de TareasContext oara que pueda ser inyecta a CategoriaService correctamente
¿Qué puedo hacer si Visual Studio Code no detecta bien mis archivos C#?
verifica si están con la extension .cs ademas debes tener instalado en extension el devpack de c#
Hola me genera un error y no logro resolverlo requiero su ayuda please!
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.CategoriaService'.) (Error while validating the service descriptor 'ServiceType: webapi.Services.ITareasService Lifetime: Scoped ImplementationType: webapi.Services.TareasService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.TareasService'.)
---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: webapi.Services.ICategoriaService Lifetime: Scoped ImplementationType: webapi.Services.CategoriaService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.CategoriaService'.
---> System.InvalidOperationException: Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.CategoriaService'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1 serviceDescriptors, ServiceProviderOptions options) --- End of inner exception stack trace --- at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter1.CreateServiceProvider(Object containerBuilder) at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() at Program.<Main>$(String[] args) in C:\Users\57313\Documents\testTechnical\webapi\Program.cs:line 18 ---> (Inner Exception #1) System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: webapi.Services.ITareasService Lifetime: Scoped ImplementationType: webapi.Services.TareasService': Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.TareasService'. ---> System.InvalidOperationException: Unable to resolve service for type 'webapi.TareasContext' while attempting to activate 'webapi.Services.TareasService'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) --- End of inner exception stack trace --- at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor) at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1 serviceDescriptors, ServiceProviderOptions options)
Revisa si CategoriaService esta implementando ICategoriaService Este parece ser el problema
Hola, me esta arrojando este error, despues de hacer el services.AddScoped<ITareaService, TareaService>();
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: WEBAPI.Services.ITareasService Lifetime: Scoped ImplementationType: WEBAPI.Services.TareasService': Unable to resolve service for type 'WEBAPI.TareasContext' while attempting to activate 'WEBAPI.Services.TareasService'.)
Debes revisas si TareasService esta implementando la interfaz esto se hace utilizando el operador dos puntos así: TareasService : ITareaService
Hola Miguel, gracias por la respuesta, asi esta implementado:
using API.Models; using System; using System.Collections.Generic; using System.Threading.Tasks;
namespace API.Services
{ public class TareaService : ITareaService { TareasContext Context; public TareaService(TareasContext dbContext) { Context = dbContext; } public IEnumerable<Tarea> Get() { return Context.Tareas; } public async Task Save(Tarea tarea) { Context.Add(tarea); await Context.SaveChangesAsync(); } public async Task Update(Guid id, Tarea tarea) { var tareaActual = Context.Tareas.Find(id); if (tareaActual != null) { tareaActual.CategoriaId = tarea.CategoriaId; tareaActual.Titulo = tarea.Titulo; tareaActual.PrioridadTarea = tarea.PrioridadTarea; tareaActual.Descripcion = tarea.Descripcion; await Context.SaveChangesAsync(); } } public async Task Delete(Guid id) { var tareaActual = Context.Tareas.Find(id); if (tareaActual != null) { Context.Remove(tareaActual); await Context.SaveChangesAsync(); } } } public interface ITareaService { IEnumerable<Tarea> Get(); Task Save(Tarea tarea); Task Update(Guid id, Tarea tarea); Task Delete(Guid id); }
}
Que hace el atributo APIController?
VSC me marcaba error porque no tenía los métodos en la Interfaz de TareasService, solo asegurense de que estén definidos:
public interface ITareasService { IEnumerable<Tarea> Get(); Task Save(Tarea tarea); Task Update(Guid id, Tarea tarea); Task Delete(Guid id); }
Y ya con eso queda el archivo de TareaController:
using Microsoft.AspNetCore.Mvc; using webapi.Models; using webapi.Services; namespace webapi.Controllers; [Route("/api/[controller]")] public class TareaController : ControllerBase { protected readonly ITareasService _tareasService; public TareaController(ITareasService service) { _tareasService = service; } [HttpGet] public IActionResult Get() { return Ok(_tareasService.Get()); } [HttpPost] public IActionResult Post([FromBody] Tarea tarea) { _tareasService.Save(tarea); return Ok("Tarea creada"); } [HttpPut("{id}")] public IActionResult Put(Guid id, [FromBody] Tarea tarea) { _tareasService.Update(id, tarea); return Ok("Tarea actualizada"); } [HttpDelete("{id}")] public IActionResult Delete(Guid id) { _tareasService.Delete(id); return Ok("Tarea eliminada"); } }