ASP.NET Core - Usando OData no .NET 5.0
Neste artigo veremos como usar os recursos do OData em APIs ASP .NET Core com o NET 5.0. |
A partir da ASP .NET Core 2.0 foi disponiblizado o suporte a OData (Open Data Protocol) como um pacote nuget permitindo a criação de endpoints com OData v4.0 em múltiplas plataformas.
Mas o que é OData ?
O OData (Open Data Protocol) é um padrão OASIS aprovado pela ISO/IEC que define um conjunto de práticas recomendadas para criar e consumir Web APIs.
A implementação dos padrões OData torna mais fácil consumir uma API pelos seus clientes e permite a criação de consultas flexíveis e legíveis por meio das convenções da URL do OData.
Usando as convenções da URL OData, você pode expor uma API muito mais limpa e genérica e permitir que o cliente da API especifique suas necessidades por meio de requisições.
Assim o OData é um protocolo aberto que permite a criação e consumo de APIs RESTful consultáveis e interoperáveis de forma simples e padronizada. Ele descreve coisas como qual método HTTP usar para qual tipo de solicitação, quais códigos de status retornar quando e também convenções de URL. Inclui informações sobre como consultar dados - filtragem e paginação, mas também como chamar funções e ações personalizadas e muito mais.
A seguir temos algumas opções de consultas OData que podemos usar com Web API da ASP .NET Core:
A seguir veremos um exemplo prático do uso de OData em uma API ASP .NET Core.
Recursos usados:
Criando a API ASP .NET Core
Abra o VS 2019 e clique em New Project e selecione o template ASP .NET Core Web API e clique em Next;
Informe o nome ApiOData e clique em Next;
A seguir selecione o Target Framework, Authentication Type e demais configurações conforme mostrada na figura:
Não vamos usar o Swagger neste projeto.
Clique em Create.
Vamos incluir no projeto os seguintes pacotes Nuget:
Isso pode ser feito via menu Tools-> Manage Nuget Packages for Solution, selecionando a guia Browse e informando o nome do pacote ou digitando na janela do Console Package Manager:
Crie uma pasta Models no projeto e nesta pasta crie a classe Cliente:
public class Cliente { public int Id { get; set; } public string Nome { get; set; } public string Email { get; set; } public string Cidade { get; set; } public int Idade { get; set; } } |
A seguir crie uma pasta Services e nesta pasta crie a classe ClienteService:
using APIOData.Models; using System.Collections.Generic; using System.Linq; namespace APIOData.Services listaClientes.Add(new Cliente { Id = 1, Nome = "Maria Silveira", Email = "maria@email.com", Cidade = "Santos", Idade = 22 }); public List<Cliente> GetClientes() => CriaDados().ToList(); |
Neste serviço estamos definindo alguns dados para poder usar nas consultas.
Registrando os serviços e o endpoint OData
No método ConfigureServices da classe Startup vamos registrar o serviço OData , o serviço ClienteService e o serviço do NewtonsoftJson:]
public void ConfigureServices(IServiceCollection services) { services.AddControllers().AddNewtonsoftJson(); services.AddControllers(); services.AddScoped<ClienteService>(); services.AddOData(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "APIOData", Version = "v1" }); }); } ... |
A seguir precisamos definir quais as convenções vamos permitir para criar as consultas customizadas que desejamos realizar em nossa API de forma a poder usar a API já pronta sem ter que alterar nada no seu código.
No método Configure vamos habilitar a injeção de dependência para suportar rotas HTTP e a seguir definir quais opções de consultas desejamos habilitar em nossas rotas.
No exemplo estamos habilitando as opções de consulta: Expand(), Select(), Count(), OrderBy() e Filter().
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseEndpoints(endpoints => |
Com isso temos tudo pronto para usar o OData na API.
Criando a API ClientesController
Vamos criar o controlador ClientesController na pasta Controllers que representa a nossa API:
using APIOData.Services; using Microsoft.AspNet.OData; using Microsoft.AspNetCore.Mvc; namespace APIOData.Controllers public ClientesController(ClienteService clienteService) [HttpGet(nameof(GetData))] |
O atributo [EnableQuery] permite que os clientes modifiquem a consulta usando opções de consulta, como $Filter, $Select e $Expand, etc.
Testando a API usando OData
Vamos executar a API e podemos usar o Postman ou o navegador para realizar consultas.
1- Acessando o endpoint : api/clientes teremos a exibição da lista de clientes
2- https://localhost:44330/api/clientes?$select=id,nome ($select)
2- https://localhost:44330/api/clientes?$select=id,nome&$skip=2 ($skip)
2- https://localhost:44330/api/clientes?$select=id,nome&$top=2 ($top)
2- https://localhost:44330/api/clientes?$select=id,nome,idade&$top=5&$filter=idade gt 50 ($filter)
Filtrando para exibir clientes com idade maior que (gt) 50.
Os operadores padrão que podemos usar com $filter são:
Operator | Description | Example |
Comparison Operators | ||
eq | Equal | $filter=valor eq 100000 |
ne | Not Equal | $filter=valor ne 100000 |
gt | Greater than | $filter=valor gt 100000 |
ge | Greater than or equal | $filter=valor ge 100000 |
lt | Less than | $filter=valor lt 100000 |
le | Less than or equal | $filter=valor le 100000 |
Logical Operators | ||
and | Logical and | $filter=valor lt 100000 and valor gt 2000 |
or | Logical or | $filter=contains(name,'(sample)') or contains(nome,'teste') |
not | Logical not | $filter=not contains(name,'sample') |
Grouping Operators | ||
() | Precedence grouping | (contains(name,'sample') or contains(name,'test')) and valor gt 5000 |
2- https://localhost:44330/api/clientes?$select=id,nome,idade&$top=5&$filter=startswith(Nome,'P')
Usando $filter com startswith : Filtrar pelos nomes iniciando com a letra 'P'
2- https://localhost:44330/api/clientes?$select=id,nome,idade&$top=5&$orderby=nome desc ($orderby)
Podemos inclusive realizar a paginação usando os recursos do OData e vamos mostrar isso na próxima parte do artigo.
Paginação com OData
Podemos criar um
endpoint habilitado para realizar a paginação de
dados, o que significa que se você tem muitos dados em um banco de dados, e o
requisito é que o cliente precisa mostrar os dados como 10 registros por página,
é aconselhável que o próprio servidor envie esses 10 registros por
request para que toda a carga de dados não trafegue
na rede, e com isso estamos melhorando o desempenho dos serviços.
Suponha que você tenha 10.000 registros no banco de dados, então você pode
habilitar seu endpoint para retornar 10 registros e considerar o
request para o registro inicial e o número de registros a serem enviados.
Nesse caso, o cliente fará uma solicitação toda vez que a opção de paginação de
busca do próximo conjunto de registros for usada ou o usuário navegar para a
próxima página.
Para habilitar a paginação, basta mencionar a contagem de páginas no atributo [Queryable].
Ex: [EnableQuery(PageSize=5)]
Observe que informamos o pagesize no atributo indicando o tamanho da página.
[HttpGet] [EnableQuery(PageSize = 5)] public IActionResult GetData() => Ok(_clienteService.GetClientes());
|
Além disso podemos também colocar restrições em suas opções de consulta. Suponha que você não queira que o cliente acesse opções de filtragem ou opções de ignorar; então, no nível de ação, você pode colocar restrições para ignorar esse tipo de request na API.
As Query Option ou opções de restrições podem ser dos seguintes tipos:
Pegue o projeto implementado aqui: APIOData.zip (sem as referências)
"Que diremos, pois, a estas coisas? Se Deus é por
nós, quem será contra nós?"
Romanos 8:31
Referências:
ASP .NET Core 2 - MiniCurso Básico
ASP .NET Core - Macoratti
Conceitos - .NET Framework versus .NET Core
ASP .NET Core - Conceitos Básicos
ASP .NET Core MVC - CRUD básico com ADO .NET
ASP .NET Core - Implementando a segurança com .
ASP .NET Core - Apresentando Razor Pages
Minicurso ASP .NET Core 2.0 - Autenticação com JWT - I
Minicurso ASP .NET Core 2.0 - Autenticação com JWT - II