Jas*_*son 5 asp.net-core-webapi swashbuckle.aspnetcore asp.net-core-odata
我遇到了 OData 8.x 和属性路由的问题,其中同一控制器操作生成重复路由。此重复路线导致 Swagger / Swashbuckle 抛出“方法/路径组合冲突”错误。
我已经能够将其简化为Visual Studio 2019 中稍微调整的默认天气预报模板。
// Change name of controller to plural
// Added Route() attribute
// Changed ControllerBase to ODataController (issue happens with ControllerBase too)
[Route("api/[controller]")]
public class WeatherForecastsController : ODataController{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet()]
public IEnumerable<WeatherForecast> Get() {
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast {
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
添加 OData 就像将调用包含AddOData()在Startup.cs
private IEdmModel GetEdmModel() {
var builder = new ODataConventionModelBuilder();
builder.EntitySet<WeatherForecast>("WeatherForecasts");
return builder.GetEdmModel();
}
public void ConfigureServices(IServiceCollection services) {
services
.AddControllers()
// Added this AddOData call
.AddOData(opt => {
opt
.Count()
.Filter()
.Select()
.OrderBy()
.SetMaxTop(20)
.AddRouteComponents("api", GetEdmModel());
});
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "SwaggerODataTest", Version = "v1" });
});
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,控制器中只有一个默认方法——即定义了一个端点。Get()然而添加属性Route()会导致以下异常
Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException:
Conflicting method/path combination "GET api/WeatherForecasts" for actions -
SwaggerODataTest.Controllers.WeatherForecastsController.Get (SwaggerODataTest),
SwaggerODataTest.Controllers.WeatherForecastsController.Get (SwaggerODataTest).
Actions require a unique method/path combination for Swagger/OpenAPI 3.0.
Use ConflictingActionsResolver as a workaround
Run Code Online (Sandbox Code Playgroud)
看起来 OData 和 ASP.NET Core (??) 都在处理同一个控制器两次并生成重复的(冲突的)端点。难道我做错了什么?有没有办法告诉 ASP.NET Core 不要解析控制器来生成路由端点并让 OData 来完成?
小智 3
AddRouteComponents 基于 OData 路由约定添加路由 ( https://learn.microsoft.com/en-us/odata/webapi/built-in-routing-conventions )
以下是一个很好的解释: /sf/answers/4743492561/
只需删除控制器中的 Route 和 HttpGet 属性,它就应该可以工作。
我刚刚开始使用 OData,所以我也很挣扎:-)。在这种情况下,以下信息对于其他正在挣扎的人来说是有用的信息......
我执行以下操作(在 ASP.Net Core 6program.cs 中,但逻辑可以轻松转移到 ASP.Net Core 5startup.cs)以拥有 $top、$count、[controller](key)、[controller]/钥匙等等。我在此示例中使用实体框架(.Net 6、Sql Server)。
string connectionString = builder.Configuration.GetConnectionString("ExampleDb");
builder.Services.AddDbContext<ExampleDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddControllers().AddOData(options => {
options.EnableQueryFeatures();
var routeOptions = options.AddRouteComponents(EdmModelBuilder.GetEdmModel()).RouteOptions;
routeOptions.EnableQualifiedOperationCall =
routeOptions.EnableKeyAsSegment =
routeOptions.EnableKeyInParenthesis = true;
});
Run Code Online (Sandbox Code Playgroud)
这位于单独的 EdmModelBuilder.cs 文件中。(测试是.Net 6实体框架模型)
public static class EdmModelBuilder {
public static IEdmModel GetEdmModel() {
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Test>("Test");
return builder.GetEdmModel();
}
}
Run Code Online (Sandbox Code Playgroud)
这在我的控制器中。(键可以是另一个主要数据类型或字符串;IActionResult 与 swagger 配合良好;没有 Route 或 HttpGet 属性)
public class TestController : ODataController {
private readonly ExampleDbContext _context;
private readonly ILogger<TestController> _logger;
public TestController(ILogger<TestController> logger, ExampleDbContext context) {
_logger = logger;
_context = context;
}
[EnableQuery(PageSize = 10)]
public IActionResult Get() {
return Ok(_context.Test);
}
public IActionResult Get(int key) {
return Ok(_context.Test.SingleOrDefault(c => c.Id == key));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2430 次 |
| 最近记录: |