How to add URL path version to ODataController using attribute routing in OData 8.x #1095
-
I am trying out version interleaving example with URL path version + OData, but I could not get OData to recognize the versions on the controller as expected with route attribute. I am looking for guidance for how to setup URL path version correctly with OData 8.x .NET version6.0 Package versions<PackageReference Include="Asp.Versioning.OData" Version="6.4.0" />
<PackageReference Include="Microsoft.AspNetCore.OData" Version="8.2.5" /> Routes that I want
Setup code:var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers().AddOData(options =>
{
options.Select().Filter();
});
builder.Services.AddApiVersioning().AddOData(
options =>
{
options.ModelBuilder.DefaultModelConfiguration = (builder, apiVersion, routePrefix) =>
{
builder.EntitySet<WeatherForecast>("WeatherForecast");
};
options.AddRouteComponents("api/v{version:apiVersion}");
});
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseODataRouteDebug();
app.UseRouting();
app.MapControllers();
app.Run(); Controller:namespace InterleavingVersions.Controllers
{
[ApiVersion(1.0)]
[ApiVersion(2.0)]
[ApiVersion(3.0)]
// [Route("api/v{version:apiVersion}")] -> adding this header will result in runtime exception at startup time. see the exception in the below
public class WeatherForecastController : ODataController
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
// Conventional
[EnableQuery]
[HttpGet]
public IQueryable<WeatherForecast> Get()
{
return new[] { new WeatherForecast() { Id = "v1" } }.AsQueryable();
}
// Attribute WITHOUT the version prefix
[EnableQuery]
[HttpGet("WeatherForecast"), MapToApiVersion(2.0)]
public IQueryable<WeatherForecast> GetV2()
{
return new[] { new WeatherForecast() { Id = "v2" } }.AsQueryable();
}
// Attribute WITH the version prefix
[EnableQuery]
[HttpGet("api/v{version:apiVersion}/WeatherForecast"), MapToApiVersion(3.0)]
public IQueryable<WeatherForecast> GetV3()
{
return new[] { new WeatherForecast() { Id = "v3" } }.AsQueryable();
}
}
} Actual OData routes:Expected vs actual
Note that since 8.0, ASP.NET Core OData deprecated the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Navigating the mess that is OData routing conventions is daunting. I empathize. Observations
Honestly, I don't think I have a lot of examples of version interleaving with OData. This is probably due to the version-to-EDM affinity, but it is possible and supported. SolutionTo make things work the way you want, this simple change should do the trick: [ApiVersion( 1.0 )]
[ApiVersion( 2.0 )]
[ApiVersion( 3.0 )]
public class WeatherForecastsController : ODataController
{
[EnableQuery]
public IQueryable<WeatherForecast> Get() =>
new WeatherForecast[] { new() { Id = "v1" } }.AsQueryable();
[EnableQuery]
[ActionName( nameof( Get ) )]
[MapToApiVersion( 2.0 )]
public IQueryable<WeatherForecast> GetV2() =>
new WeatherForecast[] { new() { Id = "v2" } }.AsQueryable();
[EnableQuery]
[ActionName( nameof( Get ) )]
[MapToApiVersion( 3.0 )]
public IQueryable<WeatherForecast> GetV3() =>
new WeatherForecast[] { new() { Id = "v3" } }.AsQueryable();
}
|
Beta Was this translation helpful? Give feedback.
Navigating the mess that is OData routing conventions is daunting. I empathize.
Observations
UseRouting()
as that is done for you (it worked for me without it)a. This means you should have
WeatherForecasts
andWeatherForecast
a. There can only be one
Get
in code, which is enforced by the compilerb.
GetV2
will never be seen or treated as matchingGet
without some helpHonestly, I don't think I have a lot of examples of version interleaving with OData. This is …