What is OData?

OData (Open Data Protocol) is a standard that helps developers build and use RESTful APIs more easily. It provides a set of rules and guidelines for how APIs should handle things like requests, responses, filtering data, sorting, and more. With OData, you don’t have to worry about the technical details of how to structure your API—it takes care of things like HTTP methods, query options (like filtering and sorting), and data formats for you. It also includes advanced features like tracking changes, defining reusable functions, and handling batch requests. You would find connectors for OData in Power BI, MS-Excel etc., that makes it easier to consume the APIs from multiple clients. In short, OData makes it simpler to create APIs that are powerful, consistent, and easy to use.

How to create OData API using .NET 8

Using Visual Studio Code, create an API using webapi template.
Type the below command in the terminal

dotnet new webapi --use-controllers -o MyRestApi
cd MyRestApi

This will create boilerplate code to create a REST API.

To further enable OData support for API, we need to make few changes. Below are the steps and code modifications required:

1. Install OData NuGet Package

Run the following command in the terminal to install the OData package:

dotnet add package Microsoft.AspNetCore.OData

2. Update Startup.cs to Configure OData

Modify the Startup.cs file to add OData services and configure the OData routing.

using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;
using MyRestApi.Models;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers()
                .AddOData(opt =>// Add OData services
                {
                    var builder = new ODataConventionModelBuilder();//builder for OData
                    builder.EntitySet<WeatherForecast>("WeatherForecast");// Define the entity set for WeatherForecast
                    opt.AddRouteComponents("odata", builder.GetEdmModel());
                });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

AddOData Registers and adds OData in the Dependency Container.

AddRouteComponents method is used to register a route, passing along the Edm model to associate it with.

ODataConventionalModelBuilder is used to build the Edm model.

UseRouting adds route matching to the middleware pipeline.

UseEndpoints adds endpoint execution to the middleware pipeline.

3. Modify WeatherForecastController to Support OData

Update the controller to inherit from ODataController. Update action methods with [EnableQuery]. The method should return IQueryable type for OData query support.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using System.Linq;
using MyRestApi.Models;
using MyRestApi.Services;
using Microsoft.AspNetCore.OData.Routing.Controllers;

namespace MyRestApi.Controllers
{
    public class WeatherForecastController : ODataController
    {
        private readonly WeatherService _weatherService;

        public WeatherForecastController(WeatherService weatherService)
        {
            _weatherService = weatherService;
        }

        [EnableQuery]// Enable OData query options
        public IQueryable<WeatherForecast> Get()
        {
            return _weatherService.GetForecast().AsQueryable();// Return the forecast data as IQueryable to support OData query options
        }
    }
}

EnableQuery attribute automatically applies the query options to the results returned by the controller action.

4. Ensure WeatherService Returns a Queryable Collection

Update the WeatherService to ensure it returns a collection that can be queried.

using System.Collections.Generic;
using MyRestApi.Models;

namespace MyRestApi.Services
{
    public class WeatherService
    {
        public IEnumerable<WeatherForecast> GetForecast()
        {
            return new List<WeatherForecast>
            {
                new WeatherForecast { Date = DateTime.Now, TemperatureC = 25, Summary = "Sunny" },
                new WeatherForecast { Date = DateTime.Now.AddDays(1), TemperatureC = 22, Summary = "Cloudy" },
                new WeatherForecast { Date = DateTime.Now.AddDays(2), TemperatureC = 18, Summary = "Rainy" }
            }.AsQueryable();//OData query options;
        }
    }
}

5. Test the OData API

Run the application and test the OData endpoints. For example:

  • GET /odata/WeatherForecast - Retrieves all forecasts.
  • GET /odata/WeatherForecast?$filter=TemperatureC gt 20 - Filters forecasts where temperature is greater than 20°C.
  • GET /odata/WeatherForecast?$orderby=Date desc - Orders forecasts by date in descending order.

These changes will enable OData functionality in your API, allowing clients to query data using OData conventions.