Neste post daremos continuidade a uma série de postagens sobre Web-Services divididos entre conceitos teóricos e praticos. Nos 3 primeiros posts focou-se em teoria com um sobre Web Services, outro sobre RESTful Web Services e mais um sobre os HTTP Status Codes mais comuns. Este post por sua vez complementa a parte teórica e o que foi desenvolvido na série de posts em que implementamos API’s REST com SpringBoot. Faremos aqui uma abordagem das mesmas situações só que dessa vez com a tecnologia ASP.NET Core. Além disso o código desse projeto se baseia no post anterior Criando um endpoint REST com ASP.NET Core. Então antes de começar confira o post Criando uma simples Web API RESTful em .NET Core 2.0.
Agora faremos algumas alterações no projeto original. Para começar crie os seguintes source folders Models, Services e dentro de Services Implementations. A estrutura da nossa arquitetura deve ficar similar a imagem abaixo.
Feito isto crie uma classe chamada Person, no source folder Models, com as informações que serão representadas pelo nosso endpoint REST.
namespace SimpleRestfulAPIWithAspNetCore.Models { public class Person { public long Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Address { get; set; } } }
Feito isto crie uma interface com o nome IPersonService no source folder Services.
using SimpleRestfulAPIWithAspNetCore.Models; using System.Collections.Generic; namespace SimpleRestfulAPIWithAspNetCore.Services { public interface IPersonService { Person Create(Person person); Person FindById(string personId); List<person> FindAll(); Person Update(Person person); void Delete(string personId); } }
Agora vamos criar a implementação para a interface PersonService. No source folder Services –> Implementations crie a classe PersonServiceImpl que implementa a interface que acabamos de criar.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using SimpleRestfulAPIWithAspNetCore.Models; using System.Threading; namespace SimpleRestfulAPIWithAspNetCore.Services.Implementations { public class PersonServiceImpl : IPersonService { // Contador responsável por gerar um fake ID já que não estamos // acessando nenhum banco de dados private volatile int count; // Metodo responsável por criar uma nova pessoa // Se tivéssemos um banco de dados esse seria o // momento de persistir os dados public Person Create(Person person) { return person; } // Método responsável por retornar uma pessoa // como não acessamos nenhuma base de dados // estamos retornando um mock public Person FindById(string personId) { return new Person { Id = IncrementAndGet(), FirstName = "Leandro", LastName = "Costa", Address = "Uberlândia - Minas Gerais - Brasil" }; } // Método responsável por retornar todas as pessoas // mais uma vez essas informações são mocks public List<person> FindAll() { List<person> persons = new List<person>(); for (int i = 0; i < 8; i++) { Person person = MockPerson(i); persons.Add(person); } return persons; } // Método responsável por atualizar uma pessoa // por ser mock retornamos a mesma informação passada public Person Update(Person person) { return person; } // Método responsável por deletar // uma pessoa a partir de um ID public void Delete(string personId) { //A nossa lógica de exclusão viria aqui } // Método responsável por mockar uma pessoa private Person MockPerson(int i) { return new Person { Id = IncrementAndGet(), FirstName = "Person Name " + i, LastName = "Last Name " + i, Address = "Some Address in Brasil " + i }; } public Int32 IncrementAndGet() { return Interlocked.Increment(ref count); } } }
Por fim renomeie a classe ValuesController para PersonController, após as alterações esse será o controller responsável por expor o endpoint de pessoas, no source folder Controllers.
using Microsoft.AspNetCore.Mvc; using SimpleRestfulAPIWithAspNetCore.Models; using SimpleRestfulAPIWithAspNetCore.Services; namespace SimpleRestfulAPIWithAspNetCore.Controllers { /* Mapeia as requisições de http://localhost:{porta}/api/person/ Por padrão o ASP.NET Core mapeia todas as classes que extendem Controller pegando a primeira parte do nome da classe em lower case [Person]Controller e expõe como endpoint REST */ [Route("api/[controller]")] public class PersonController : Controller { //Declaração do serviço usado private IPersonService _personService; /* Injeção de uma instancia de IPersonService ao criar uma instancia de PersonController */ public PersonController(IPersonService personService) { _personService = personService; } //Mapeia as requisições GET para http://localhost:{porta}/api/person/ //Get sem parâmetros para o FindAll --> Busca Todos [HttpGet] public IActionResult Get() { return Ok(_personService.FindAll()); } //Mapeia as requisições GET para http://localhost:{porta}/api/person/{id} //recebendo um ID como no Path da requisição //Get com parâmetros para o FindById --> Busca Por ID [HttpGet("{id}")] public IActionResult Get(string id) { var person = _personService.FindById(id); if (person == null) return NotFound(); return Ok(person); } //Mapeia as requisições POST para http://localhost:{porta}/api/person/ //O [FromBody] consome o Objeto JSON enviado no corpo da requisição [HttpPost] public IActionResult Post([FromBody]Person person) { if (person == null) return BadRequest(); return new ObjectResult(_personService.Create(person)); } //Mapeia as requisições PUT para http://localhost:{porta}/api/person/ //O [FromBody] consome o Objeto JSON enviado no corpo da requisição [HttpPut] public IActionResult Put([FromBody]Person person) { if (person == null) return BadRequest(); return new ObjectResult(_personService.Update(person)); } //Mapeia as requisições DELETE para http://localhost:{porta}/api/person/{id} //recebendo um ID como no Path da requisição [HttpDelete("{id}")] public IActionResult Delete(string id) { _personService.Delete(id); return NoContent(); } } }
Agora que terminamos nossa codificação inicie a aplicação. Para testar nosso endpoint e cada uma de suas operações usaremos o plugin do Chrome Postman.
Primeiro faremos uma requisição do tipo GET chamando a operação findAll para o recurso http://localhost:{porta}/api/person/. Como se pode ver na imagem abaixo obtemos como resposta um JSON com um array de pessoas.
Agora faremos uma requisição do tipo GET chamando a operação http://localhost:{porta}/api/person/1 passando como variável path o ID da pessoa que desejamos recuperar. Da mesma forma que na requisição anterior recebemos como resposta um JSON com 1 objeto pessoa.
Agora faremos uma requisição do tipo POST (esse é o verbo REST usado para persistir informações) chamando a operação http://localhost:{porta}/api/person/ passando como parâmetro um JSON com um objeto pessoa no corpo da requisição. Para isso no Postman precisamos setar o tipo de requisição como POST, na aba Body definimos o JSON que representa o objeto pessoa a ser gravado, selecionamos a opção raw, definimos a opção JSON(application/json) e por fim executamos a request através do botão send.
Agora faremos uma requisição do tipo PUT (esse é o verbo REST usado para atualizar informações) chamando a operação http://localhost:{porta}/api/person/ passando como parâmetro um JSON com um objeto pessoa no corpo da requisição. Lembrando que essa representação de pessoa deve ter um ID que será usado pra localizar e atualizar um recurso na base. Para isso no Postman precisamos setar informações similares ao post a unica diferença é que o tipo de requisição deve ser o PUT.
Por fim faremos uma requisição do tipo DELETE (verbo REST usado excluir informações) chamando a operação http://localhost:{porta}/api/person/1 passando como variável path o ID da pessoa que desejamos remover da base. Esse tipo de requisição retorna como resposta um body vazio e um StatusCode 200 caso a operação seja executada com sucesso os StatusCode 204 (no content), 401 (Unauthorized), 403 (forbiden), 404 (not found) ou 500 (internal server error) podem ser retornados.
Dessa forma abordamos os 4 verbos principais do HTTP usados em aplicações REST. Continue ligado no blog, por que no próximo post iremos documentar a nossa API com o framewrok Swagger. E claro a abordagem nesses posts também será totalmente mão na massa. É isso aí bons estudos.
Treinamentos relacionados com este post