Unas de las ventajas de usar webservices con net core, es la robustes de la plataforma, todas esas herramientas que .net tiene, esa infraestructura que manejan y la facilidad de ir escalando, por eso vamos a centrarnos un poco mas en webservices con net core.
Creando nuestro webservices con net core
Vamos a abrir VS2017 y vamos a crear un nuevo proyecto
Vamos elegir asp.net core web application y luego vamos a ver la siguiente página.
Una vez creado todo le damos click al botón de play o ctrl + f5 para ejecutar la app y vamos a ver lo siguiente.
Inmediatamente podemos ver que ya tenemos un webservices funcionando con una respuesta en JSON.
Nuestro siguiente punto es crear otro modelo y otras rutas para poder consumir.
Vamos a agregar una nueva carpeta llamada Models y luego un modelo para esto vamos a hacerlo de la siguiente manera.
Luego seleccionamos la carpeta y hacemos lo mismo solo que ahora vamos a elegir Class
Una vez creada nuestra clase vamos a agregar a la case las siguiente propiedades
public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; }
esto quedara de la siguiente manera
namespace uptuto1.Models { public class TodoItem { public long Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } } }
Agregando database context
Ahora vamos a usar un poco de Entity Framework para esto vamos a usar la clase de Microsoft.EntityFrameworkCore.DbContext , para esto vamos a agregar una nueva clase en models llamada TodaContext y quedaría de la siguiente manera
namespace uptuto1.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } } }
Con esto ya podremos usar entity Framework con las bases de datos.
Registro nuestro db context en nuestro webservices con net core
Cuando hacemos un webservices con net core, los servicios como por ejemplo el db Context que acabamos de crear deben ser registradas en el contenedor de dependencias de inyeccion, ya que proporciona el servicio a los controladores.
Ahora vamos a ir a nuestro archivo Startup .cs y vamos a actualizar un poco para dar de alta nuestro servicio.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using uptuto1.Models; using Microsoft.EntityFrameworkCore; namespace uptuto1 { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList")); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); } } }
En poca palabras, hacemos referencia a los models y exportamos el entity framework para .net core, en configure serves agregamos la siguiente linea:
services.AddDbContext(opt =>
opt.UseInMemoryDatabase(«TodoList»));
Con esto estamos listo para el siguiente paso.
Controller para nuestro webservices con net core
Una de las cosas que vamos a hacer es usar un controller, con esto le diremos a nuestra api rest que hacer cuando llegue una peticion, específicamente vamos a conectar con nuestro dbContext, para poder hacer un CRUD.
Nuestro clase del controlador se vera de la siguiente manera
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using uptuto1.Models; namespace uptuto1.Controllers { [Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly TodoContext _context; public TodoController(TodoContext context) { _context = context; if (_context.TodoItems.Count() == 0) { // Create a new TodoItem if collection is empty, // which means you can't delete all TodoItems. _context.TodoItems.Add(new TodoItem { Name = "Item1" }); _context.SaveChanges(); } } } }
Ya tenemos nuestro método principal ahora vamos a agregar métodos para que nuestra ruta haga algo especifico.
// GET: api/Todo [HttpGet] public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); } // GET: api/Todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }
Del cual quedaria el controlador de la siguiente manera
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using uptuto1.Models; namespace uptuto1.Controllers { [Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly TodoContext _context; public TodoController(TodoContext context) { _context = context; if (_context.TodoItems.Count() == 0) { // Create a new TodoItem if collection is empty, // which means you can't delete all TodoItems. _context.TodoItems.Add(new TodoItem { Name = "Item1" }); _context.SaveChanges(); } } // GET: api/Todo [HttpGet] public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); } // GET: api/Todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; } } }
Si hacemos una consulta get a la ruta todo nos va a parecer la siguiente respuesta.
Explicación
Estamos usando [HttpGet] que es un método que responde a http Get request.
Vamos a analizar una de las llamadas para explicar que pasa y como podemos hacer algo mas.
[Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly TodoContext _context;
Podemos ver controller, en esta parte es sustituido por el nombre de nuestro controlador, en este caso TodoController lo que toma es el nombre todo, esto sirve para hacer el ruteo para nuestro webservices con net core.
// GET: api/Todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }
[HttpGet] Este es el atributo para hacer las llamadas al webservices de un tipo especifico, en este caso le estamos diciendo que es del tipo get.
Si nosotros colocamos por ejemplo [HttpGet(«/products»)] estamos diciendo que va a hacer un get a esa ruta.
El tipo de retorno de los métodos GetTodoItems
y GetTodoItem
son del tipo ActionResult <T> , asp.net core por default serializa los objetos en Json, y es el mensaje que nos da al consultar.
Cuando todo sale bien la respuesta es 200 y so hay algun error de excepcion no controlada es 5xx, cuando no encuentra un metodo nos regresa 404 esto son los valores que te da ActionResult.
Método post en nuestro webservices con net core
Para usar el método post debemos colocar el siguiente atributo:
[HttpPost] Es la forma de llamar al metodo http request post, y leer lo que trae en el cuerpo. esto lo ponemos antes de nuestra función.
// POST: api/Todo [HttpPost] public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); }
Podemos hacer la prueba en nuestro postman llamando con las propiedades de nuestro modelo
CreatedAtAction
:
- Devuelve una respuesta 201. HTTP 201 es la respuesta estándar para un método HTTP POST que crea un nuevo recurso en el servidor.
- Agrega un encabezado de localización en la respuesta. El encabezado de ubicación especifica el URI del elemento de tarea pendiente recién creado. Para obtener más información, consulte 10.2.2 201 Creado .
- Utiliza la ruta denominada «GetTodo» para crear la URL. La ruta denominada «GetTodo» se define en
GetTodoItem
:
// GET: api/Todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }
Agregar método PUT
Como vimos en los puntos anterior para usar put tenemos que agregar el siguiente metodo
[HttpPut(«{id}»)] – Para este elemento es muy similar al POST, tenemos que pasar el id y el modelo que deseamos cambiar, la respuesta de http put es 204 (no content) , por norma para hacer una actualización debemos enviar todo el modelo y no solo la actualización, el código queda de la siguiente manera.
// PUT: api/Todo/5 [HttpPut("{id}")] public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; await _context.SaveChangesAsync(); return NoContent(); }
En nuestro postman hacemos el cambio de nuestros valores por ejemplo
{ "ID":1, "name":"Hola mundo", "isComplete":true }
En caso de que hagamos algo mal nos traerá lo siguiente
Agregar Delete en nuestro webservices con net core
Por ultimo vamos a agregar nuestra petición delete, para esto vamos a usar (si igual que en los demas) nuestro método [httpDelete]
Este nos va a traer la respuesta 204 (No Content) y necesitamos el id del elemento a eliminar para que funcione bien.
// DELETE: api/Todo/5 [HttpDelete("{id}")] public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return todoItem; }
Con esto tenemos nuestro primer webservices con net core, conocemos conceptos básicos y aunque sin seguridad pero ya podemos hacer nuestras primeras funciones y llamadas, recuerden que pueden consumir esto con cualquier lenguaje por http.
Buen dia, vengo de ASP.net donde estaba acostumbrado a crear una pagina ASMX y dentro de ella crear todos los WebServices y llamarlos por su nombre, estoy CLARO que el concepto se maneja distinto en ASP MVC entityFrameWork Core etc. Baje el codigo de GibHud y obviamente funciona bien PERO pareciese q tuviese q crear un controlador por cada accion distinta, podrias ayudarme o mostrarme algun ejemplo tuyo o de tercero donde pueda crear distintos webservices… dudo q tenga q crear un archivo API por cada webservices o es asi ? Saludos y gracias