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




