Web API – OData with .NET 5

By | 20/10/2021

In this post, we will see how to implement OData with .NET 5.
First of all, what is OData?
From OData.org:
OData (Open Data Protocol) is an ISO/IEC approved, OASIS standard that defines a set of best practices for building and consuming RESTful APIs. OData helps you focus on your business logic while building RESTful APIs without having to worry about the various approaches to define request and response headers, status codes, HTTP methods, URL conventions, media types, payload formats, query options, etc. OData also provides guidance for tracking changes, defining functions/actions for reusable procedures, and sending asynchronous/batch requests.”
In a nutshell with OData it is possible querying, filtering or paging data comes from a Web API.

We start creating a WebAPI project called PostOData where, we will add these files:

[USER.CS]

namespace PostOData.Domain.Entities
{
    public class User
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Country { get; set; }
    }
}



[IUSERCONTROLLERSERVICE.CS]

using PostOData.Domain.Entities;
using System.Collections.Generic;

namespace PostOData.Application.Interfaces
{
    public interface IUserControllerService
    {
        List<User> GetListUser();
    }
}



[USERCONTROLLERSERVICE.CS]

using PostOData.Application.Interfaces;
using PostOData.Domain.Entities;
using System.Collections.Generic;

namespace PostOData.Application.ControllerServices
{
    public class UserControllerService : IUserControllerService
    {
        public List<User> GetListUser()
        {
            List<User> lstUser = new();

            for (int i = 1; i < 500; i++)
            {
                lstUser.Add(new User
                {
                    Id = i,
                    Country = i % 2 == 0 ? "EU" : "US",
                    UserName = $"UserName_{i}",
                    Password = $"Password_{i}"
                });
            }

            return lstUser;
        }
    }
}



Then, we will add a new Controller called UserController:

[USERCONTROLLER.CS]

using Microsoft.AspNetCore.Mvc;
using PostOData.Application.Interfaces;

namespace PostOData.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class UserController : ControllerBase
    {
        IUserControllerService _userControllerService;
        public UserController(IUserControllerService userControllerService)
        {
            _userControllerService = userControllerService;
        }

        [HttpGet]
        public IActionResult GetUsers()
        {
            return Ok(_userControllerService.GetListUser());
        }
    }
}



Finally, we will add the dependency injection for the UserControllerService in Startup file:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddScoped<IUserControllerService, UserControllerService>();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "PostOData", Version = "v1" });
    });
}



Now, using Postman, we will check everything works fine:

Perfect, It works fine.
Now, we will implement OData in the project.

First of all, we have to install two libraries:
Microsoft.AspNetCore.Mvc.NewtonsoftJson
Microsoft.AspNetCore.OData

IMPORTANT: Currently (September 2021) for Microsoft.AspNetCore.OData I had to install the version 7.5.10 in order to avoid problems and bugs.

Then, we have to modify the controller and the Startup file, in order to enable OData

[USERCONTROLLER.CS]

using Microsoft.AspNet.OData;
using Microsoft.AspNetCore.Mvc;
using PostOData.Application.Interfaces;

namespace PostOData.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class UserController : ControllerBase
    {
        IUserControllerService _userControllerService;
        public UserController(IUserControllerService userControllerService)
        {
            _userControllerService = userControllerService;
        }

        [HttpGet]
        [EnableQuery]
        public IActionResult GetUsers()
        {
            return Ok(_userControllerService.GetListUser());
        }
    }
}



[STARTUP.CS]

using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using PostOData.Application.ControllerServices;
using PostOData.Application.Interfaces;

namespace PostOData
{
    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.AddControllers().AddNewtonsoftJson(); // we need Newtonsoft in order to use OData
            services.AddOData(); // we register OData service

            services.AddControllers();
            services.AddScoped<IUserControllerService, UserControllerService>();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "PostOData", Version = "v1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PostOData v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.EnableDependencyInjection();
                // we register the OData endpoints
                endpoints.Select().Count().Filter().OrderBy().MaxTop(100).SkipToken().Expand();
            });
        }
    }
}



We have done and now, if we run the WebAPI, we will see some some OData commands:

SELECT

FILTER

SKIP

TOP


PAGING


ORDER BY



Leave a Reply

Your email address will not be published. Required fields are marked *