Skip to content

Feature: Implement ASP.NET Core OData v8 with Swagger/OpenAPI #1157

@PoulSteffensen

Description

@PoulSteffensen

Summary
Integrate ASP.NET Core OData v8 into the Web API project of dotnet-starter-kit and expose OData endpoints through Swagger/OpenAPI. This gives clients rich, standardized query capabilities ($filter, $select, $expand, $orderby, $top, $skip, $count) while keeping our API surface minimal and discoverable via Swagger UI. Implementation follows Microsoft's OData guidance and Swashbuckle setup for ASP.NET Core.


Why this belongs in dotnet-starter-kit

  • Powerful querying with fewer endpoints: Built-in OData query options reduce the need for custom endpoints and fit admin/back-office/reporting scenarios.
  • Modern, supported stack: ASP.NET Core OData v8 is actively maintained; OData .NET 8 modernizes internals on recent .NET versions.
  • Discoverability via Swagger/OpenAPI: Swashbuckle provides interactive docs; newer ASP.NET Core templates require explicit OpenAPI/Swagger configuration.

References


Scope (for this repository)

Projects/paths
Assume the Web API entry point is src/apps/webapi/Program.cs. We’ll update docs if paths differ.

  1. Add OData package

    • Add Microsoft.AspNetCore.OData to the Web API project.
  2. Register OData services & EDM

    • Build an EDM model (ODataConventionModelBuilder) and register route components under /odata.
    • Enable query options: .Select().Filter().OrderBy().Expand().Count().SetMaxTop(null).
  3. Create sample controller(s)

    • Inherit from ODataController and annotate GET actions with [EnableQuery].
  4. Wire up Swagger/OpenAPI

    • Add Swashbuckle packages, then AddSwaggerGen(), UseSwagger(), UseSwaggerUI() in Program.cs.
    • Confirm OData endpoints operate and Swagger loads without formatter conflicts (workarounds exist if needed).
  5. Documentation

    • Update kit docs (e.g., /docs or README) with examples & screenshots:
      • GET /odata/Products?$filter=Price gt 20
      • GET /odata/Products?$select=Id,Name&$orderby=Name
      • GET /odata/Products?$expand=Category&$count=true

Proposed Implementation (starter-kit aligned)

src/apps/webapi/Program.cs (illustrative—adapt to actual path/namespaces)

using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;

var builder = WebApplication.CreateBuilder(args);

// Swagger / OpenAPI
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// OData EDM
var odataModelBuilder = new ODataConventionModelBuilder();
// Replace with a real entity from the kit (e.g., Products, Tenants, Users)
odataModelBuilder.EntitySet<Product>("Products");

builder.Services
    .AddControllers()
    .AddOData(opt => opt
        .Select().Filter().OrderBy().Expand().Count().SetMaxTop(null)
        .AddRouteComponents("odata", odataModelBuilder.GetEdmModel()));

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
    // Optional: app.UseODataRouteDebug(); // exposes ~/$odata routing page
}

app.UseRouting();
// keep existing auth/tenant middleware as-is
app.MapControllers();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions