我的控制器看起来像:
namespace ...Api.Versions.v1.Controllers
{
[ApiController]
[ApiExplorerSettings(GroupName = "v1")]
[ApiVersion("1")]
[Route("odata/v{version:apiVersion}/[controller]")]
public class PartsController : ODataController
{
[Produces("application/json")]
[EnableQuery]
[HttpGet]
public async Task<IQueryable<Part>> Get()
{
...
}
}
}
和
namespace ...Api.Versions.v2.Controllers
{
[ApiController]
[ApiExplorerSettings(GroupName = "v2")]
[ApiVersion("2")]
[Route("odata/v{version:apiVersion}/[controller]")]
public class PartsController : ODataController
{
[Produces("application/json")]
[EnableQuery]
[HttpGet]
public async Task<IQueryable<Part>> Get()
{
...
}
}
}
我的startup.cs具有以下配置:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllers()
.AddOData(options =>
{
options.EnableQueryFeatures(maxTopValue: 8000);
options.TimeZone = TimeZoneInfo.Utc;
});
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1);
options.ReportApiVersions = true;
options.ApiVersionReader = new UrlSegmentApiVersionReader();
})
.AddMvc()
.AddOData(options =>
{
options.AddRouteComponents("odata/v{version:apiVersion}");
})
.AddODataApiExplorer(options =>
{
options.GroupNameFormat = "'v'V";
options.SubstituteApiVersionInUrl = true;
});
...
}
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
...
}
我的EDM配置如下:
namespace ...Api.Utilities.ModelConfiguration
{
using Asp.Versioning;
using Asp.Versioning.OData;
using Microsoft.OData.ModelBuilder;
public class PartModelConfiguration : IModelConfiguration
{
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion, string routePrefix)
{
switch (apiVersion.MajorVersion)
{
case 1:
ConfigureV1(builder);
break;
case 2:
ConfigureV2(builder);
break;
default:
ConfigureCurrent(builder);
break;
}
}
private void ConfigureV1(ODataModelBuilder builder) =>
ConfigureCurrent(builder);
private void ConfigureV2(ODataModelBuilder builder) =>
ConfigureCurrent(builder);
private EntityTypeConfiguration<Part> ConfigureCurrent(ODataModelBuilder builder)
{
var part = builder.EntitySet<Part>("Parts").EntityType;
part.HasKey(p => p.IdPart);
return part;
}
}
}
现在,V1和V2模型之间没有区别,这纯粹是用于测试功能。
我相信,按照本页面上的最后一节自动为DI注册上述配置:https://github.com/dotnet/aspnet-apnet-api-versioning/wiki/wiki/odata-model-configurations
我觉得我错过了一些很小的配置,但是努力寻找可能是什么。您可以从默认控制器base继承您的控制器例如:
[ApiController]
[ApiExplorerSettings(GroupName = "v1")]
[ApiVersion("1")]
[Route("odata/v{version:apiVersion}/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
[EnableQuery]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}