Back-End

17 ago, 2018

Asp.Net Web API com paginação + MySQL + EF

Publicidade

Olá, pessoal!

Hoje eu vou mostrar como criar um web service RESTful com paginação utilizando o Asp.Net Web API.

Neste artigo não vou me preocupar em fazer nenhuma validação nos dados, pois isso pode ser assunto para um outro artigo continuação. Aqui irei mostrar como criar e consumir esses dados usando o Asp.Net Web API, com a funcionalidade de paginação, que é muito útil quando se tem um grande volume de dados. Neste exemplo usaremos o Visual Studio Community 2017, o Mysql como banco de dados, e o EntityFramework para persistir os dados.

Vamos colocar a mão na massa!

Abra o Visual Studio, clique em “File” > “New Project”.

No menu lateral, escolha a opção Web, e no centro, escolha Asp.Net Web Aplicattion (.Net Framework). Na parte inferior da janela dê um nome ao seu projeto. Usei o nome WepApiMarcas. Nomeado o projeto, escolha uma pasta para salvar.

Após clicar no botão “OK“, a janela que se abre é essa:

Dentre os modelos que são oferecidos para o nosso exemplo, usei a opção vazio, o elemento Empty, como mostra a imagem acima.

Na parte de baixo da mesma janela marcaremos a opção Web API, pois assim criaremos um projeto com o mínimo possível de recursos, mas com os elementos necessários para o funcionamento correto da API. Clique no botão “OK” para finalizar.

O projeto será gerado e na imagem abaixo temos a estrutura inicial:

Com a estrutura do projeto criada, podemos instalar o EntityFramework, pois vamos precisar dele na execução da aplicação. Para instalar, clique em “References” com o botão direito e vá na opção “Manager Nuget Peckages” (gerenciador de pacotes do Nuget).

Na tela seguinte, clique em “Browser” e pesquise por EntityFramework. Feito isso, basta clicar em “Install” para que o Visual Studio faça a instalação.

Precisaremos também do EntityFramework para o Mysql, seguindo os mesmos passos mostrados anteriormente: instale-o conforme mostrado na imagem abaixo:

Com o Entity Framework instalado, vamos agora criar a nossa primeira classe dentro da pasta Models. Na pasta Models ficam as entidades que criaremos no nosso banco de dados, que representa as nossas ‘tabelas’. No nosso exemplo será apenas uma Classe.

Clique com o botão direito na pasta “Models” > “Add” > “Class“. Coloquei o nome “Marca” para essa classe.

Na classe teremos duas propriedades: o Id e a DescricaoMarca. Por padrão, o EntityFramework reconhece a propriedade Id como chave primária, que é gerada automaticamente no nosso banco de dados.

Nessa classe ainda precisamos adicionar as Data Annotations, que servem para fazer o mapeamento da tabela para a classe usando o EntityFramework. Vamos fazer as anotações como na imagem abaixo:

Adicionaremos a annotation [Table(“tb_marca”)]. O que está entre as aspas duplas representa o nome da tabela no banco de dados. Como dito antes, o EntityFramework já reconhece o campo Id como chave primária automaticamente, mas eu resolvi colocar a annotation [Key], que representa a chave primária, assim mesmo.

Pronto, feito a entidade Marca, iremos agora criar a classe de DbContext, que faz a abstração do banco de dados na nossa API. Para isso, clique com o botão direito na pasta “Models” > “Add” > “Class” e coloque o nome da classe. No meu caso, para seguir um padrão que identifique que é uma classe de contexto, eu coloquei o seguinte nome: DbMarcaContext.

A classe DbMarcaContext precisa herdar da classe DbContext dessa forma: public class DbMarcaContext : DbContext. Para isso, é necessário importar o namespace using System.Data.Entity;, e como estamos usando o Mysql, ainda precisamos adicionar a annotation [DbConfigurationType(typeof(MySqlEFConfiguration))], e para tal, importar o namespace using MySql.Data.EntityFramework;.

Veja abaixo na imagem como ficou a nossa classe:

Veja que na classe ainda subscrevemos o construtor base, personalizando a chamada da string de conexão que iremos adicionar posteriormente no Web.Config com o nome “DbMarcas”. Se não colocássemos um nome, teríamos que colocar na string de conexão o mesmo nome do construtor.

Também adicionamos uma propriedade do tipo DbSet, que colocamos o nome de “Marcas” (aqui você pode escolher qualquer nome). Essa propriedade representa a nossa tabela de marca no banco de dados.

Agora vamos no Web.Config adicionar a string de conexão. Na imagem abaixo estão as linhas que precisaremos adicionar.

Pronto, nosso Web.Config está configurado.

Lembrando que será necessário instalar o MySQL Connection para .Net, através do site. A instalação é bem tranquila, na base do Next>Next. Estou utilizando essa versão abaixo:

Após a instalação, clique com o botão direito em “References” > “AddReference“. Na tela que surge, clique em “Browser” e adicione as Dlls do MySql que estão na pasta C:\Program Files (x86)\MySQL\MySQL Connector Net 8.0.12\Assemblies\v4.5.2.

Agora vamos adicionar um Controller, que é quem recebe e responde as requisições em nossa API. Para criar a classe de Controller, na Solution Explorer clique com o botão direito no diretório “Controller” e em “Add” > “Controller“. A janela que se abre é essa:

Escolha a opção marcada, clique em “Add“, e dê um nome. No caso do exemplo, coloquei “MarcasController“.

A classe de controle é usada para manipular os dados; nela será feita a leitura, gravação, alteração e exclusão dos dados.

Vamos adicionar nessa classe DbMarcasController uma instância do DbContext e os métodos POST, PUT, GET, DELETE.

Implementaremos primeiro o método POST. Veja que importamos a using WebApiMarcas.Models; para termos acesso à classe “Marca“. Veja a imagem:

Veja que no código acima é simples inserir um registro. Usamos a interface IHttpActionResult, que lida com vários tipos de retorno. Após adicionarmos o que vem no corpo da requisição marca e salvar as alterações, o CreatedAtRoute retorna o registro inserido no banco de dados, que no caso do exemplo, é baseando na rota padrão.

Executando a aplicação, a tela que abre no Browser é essa:

Essa tela é exibida porque não há nenhuma customização amigável para nossa API, mas isso não é problema.

Para testar o funcionamento da API e o método POST, usamos o Postman, que é uma extensão que pode ser instalada no Chrome. Na imagem abaixo são exibidos a inserção e o retorno do registro, já inseridos no nosso banco de dados. A inserção é feita usando o formato Json no corpo da requisição. Ao escolher a opção POST, coloque a URL e clique em “Send“.

Agora vamos implementar o método GET. Adicione esse método na classe MarcasContoller, conforme a imagem mostra. O dbMarcas fará a consulta na entidade Marcas, fazendo a abstração com o EntityFramework, que usa o DbSet que está na classe dbMarcasContext e retornará todos os registros. Caso não encontre nada, cai na validação NotFound.

Você já pode testar a aplicação e ver retornar todos os dados usando o Postman. Selecione a opção GET, passando a URL http://localhost:61622/api/marcas (no seu caso, a porta informada na URL provavelmente será diferente), e depois clique em “Send“. Será retornada a lista de Marcas que você inseriu no banco. Para ter mais dados gravados no banco, faça vários POST usando o Postman, processo já explicado anteriormente.

No método PUT faremos uma verificação antes para ver se o id existe. Se o retorno for zero, ou seja, não encontrou nada, retornará uma mensagem de NotFound. Se passar na validação, o EntityFramework fará a alteração baseando no estado e no corpo da requisição, e aplicará as alterações.

Para método DELETE, primeiro fazemos uma consulta usando o parâmetro id e depois removemos o registro passando os dados no corpo da requisição, e salvamos as alterações.

Agora vamos para a paginação. Vamos alterar o método GET colocando os elementos para fazer a paginação. Veja como ficou:

Adicionamos dois parâmetros do tipo int no método: pagina, atribuindo o valor 1 para ele; e quantidadeRegistros, para o qual atribuímos o valor 10. Para achar o total de páginas eu faço o seguinte cálculo: int totalPaginas = (int)Math.Ceiling(dbMarca.Marcas.Count()/Convert.ToDecimal(quantidadeRegistros));

Como vocês podem ver, para obter o total de páginas, faço uma consulta em Marcas, pego a quantidade de registros do banco e divido pelo quantidadeRegistros, e depois faço um cast para transformar em inteiro. O método Math.Ceiling arredonda o valor para cima. Observação: Pagina e quantidadeRegistros são informados na url da requisição.

No trecho de código abaixo é onde é feita a paginação usando dois métodos do Linq: o Skip, que avança uma quantidade x de registros; e o Take, que pega uma quantidade de registro. Essa consulta tem que estar de forma ordenada para que fique correta. No meu caso fiz a ordenação pelo Id. Portanto, aqui será retornado de 10 em 10 registros.

var marca = dbMarca.Marcas.OrderBy(m => m.Id).Skip(quantidadeRegistros * (pagina - 1)).Take(quantidadeRegistros);

Agora vamos personalizar o cabeçalho da resposta, para que um aplicação cliente possa usar a paginação.

No trecho abaixo retornamos o total de páginas para a aplicação cliente, usando no cabeçalho da requisição o elemento X-Pages-TotalPages para informar a quantidade de páginas.

System.Web.HttpContext.Current.Response.AddHeader("X-Pages-TotalPages", totalPaginas.ToString());

Nessa linha abaixo tem uma validação para retornar a próxima página para a aplicação cliente. Usamos no cabeçalho da requisição o elemento X-Pages-NextPages para informar a URL da próxima página.

Veja que o cabeçalho está personalizado com o total de páginas e com o nextpage que a aplicação cliente irá usar para retornar os próximos registros.

Enfim, nossa API RestFull com paginação está finalizada.

Vou ficando por aqui pessoal, e até o próximo artigo.

Abraços!