Criando uma API OData v4 com ASP.NET Core

3 out

Fala Galera,

Hoje vamos falar um pouco sobre o OData (Open Data Protocol) e como podemos criar API’s Rest utilizando este protocolo. Se você já desenvolveu API’s para diversos clientes já deve ter tido o problema no qual um determinado campo no seu objeto não é necessário para um cliente porém extremamente importante para outro cliente ou mesmo que sua API precisa de um filtro mais especializado para um determinado cliente porém não é importante para outro cliente. Para estes tipos de cenários podemos utilizar o OData (Open Data Protocol) no qual o seu principal objetivo é criar API’s consultáveis, filtráveis e com interoperabilidade.

O que é Open Data Protocol (OData) ?

OData ou Open Data Protocol é uma série de padrões para construção e consumo de API. Você pode saber mais sobre o OData Protocol através de sua documentação aqui. Existem inúmeros benefícios em utilizar o padrão OData, desde a facilidade de criar padrões de consultas até a facilidade de leitura do caminho de sua API.

Dentro do OData Protocol existe as suas convenções e umas de suas principais convenções é o Query Options e é isso que torna nossas APIs flexíveis.

Query Options é usado para definir como sua API vai entregar os dados, podendo conter dados de pesquisas, filtros, ordenações, projeções e muito mais.

Abaixo um exemplo de uma API OData.

ASP.NET CORE E OData Protocol, como criar sua API OData

Vamos criar um API Rest com .NET Core utilizando o Protocolo OData, para isso vamos criar um projeto Web API conforme exemplo abaixo:

Com o projeto criado vamos adicionar a referência do pacote do OData utilizando o Package Manager Console

Install-Package Microsoft.AspNetCore.OData

Agora iremos utilizar o EntityFramework Core como nosso ORM padrão e o SQL Server como provider para realizar a persistência dos dados, para isso vamos adicionar o pacote EntityFrameworkCore.SqlServer conforme comando abaixo.

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Vamos criar uma classe de Livro e assim utilizar o Entity Framework para mapear esta classe conforme o código abaixo:

public class Book
{
    [Key]
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string ISBN { get; set; }
    public string Author { get; set;}
}

Com a nossa classe de livro criada, vamos criar o nosso contexto é nele que vamos consultar os dados do Livro conforme código abaixo

public class DataContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    public DataContext() : base()
    {
    }

    public DataContext(DbContextOptions options) : base(options)
    {
    }
}

Com o nosso contexto criado, vamos criar os nossos migrations. Para isso no terminal digite:

Add-Migration Initial
Update-Database

Muito bem, vamos agora configurar nossos serviços OData, para isso entre no Startup.cs e modifique-o conforme código abaixo:

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.AddOData();

            services.AddDbContext<DataContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("ODataSample"));
            });

            services.AddMvc().AddJsonOptions(opt =>
            {
                opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });


        }

        // 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();
            }

            app.UseMvc(o =>
            {
                o.MapODataServiceRoute("ODataRoutes", "odata", GetEdmModel());
            });
        }

        public static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            
            // Habilita funções OData como $filter, $select e etc..
            builder.EntitySet<Book>(nameof(Book))
                   .EntityType
                   .Filter()
                   .Count()
                   .Expand()
                   .OrderBy()
                   .Page()
                   .Select();

            return builder.GetEdmModel();
        }
 }

Com o nosso Startup já configurado basta agora criar um Controller, este Controller será uma API OData e para isso basta herdar da classe ODataController conforme exemplo abaixo:

[Produces("application/json")]
[Route("api/Book")]
public class BookController : ODataController
{
    private DataContext Context { get; set; }

    public BookController(DataContext context)
    {
        this.Context = context ?? throw new ArgumentNullException(nameof(context));
    }

    [HttpPost]
    public IActionResult Post([FromBody] Book model)
    {
        this.Context.Books.Add(model);
        this.Context.SaveChanges();

        return Created("/api/book/" + model.Id, model);
    }

    [EnableQuery]
    public IQueryable<Book> Get() => Context.Books.AsQueryable();
}

Pronto, nossa API OData está pronta bastando somente o consumir. Para testa-lá vamos abrir o Postman e enviar algumas requisições conforme imagem  abaixo:

Criando um novo registro

Obtendo todos os registros

Selecionando determinados campos e ordenando por Autor

E ai galera, viu como é fácil criar uma API OData com o ASP.NET Core, com uma API OData podemos criar diversas consultas especializadas com os seus filtros, paginações, seleções e etc e nossa API ganha um poder muito grande para trabalhar em cima de dados.

O código fonte deste exemplo encontra-se no meu github através deste link

Abs e até a próxima.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *