Net6 Web API中Swagger UI无法显示新增OData控制器路由求助
问题:Net6 ODataController路由未在Swagger显示且无法访问
使用带OData支持的Net6 Web API,继承ODataController而非使用[ApiController]。现有同配置控制器能正常在Swagger UI显示路由,但新增的同配置控制器路由既不显示在Swagger UI,也无法直接访问。
控制器示例代码:
public class ValuesController : ODataController { [EnableQuery(PageSize = 5)] public IQueryable<Note> Get() { return _context.Notes.AsQueryable(); } }
中间件配置示例:
builder.Services.AddControllers() .AddOData(opt => { opt.Conventions.Remove(opt.Conventions.OfType<MetadataRoutingConvention>() .First()); opt.AddRouteComponents(GetEdmModel()) .Select() .Expand() .Count() .Filter() .OrderBy().SetMaxTop(100).TimeZone = TimeZoneInfo.Utc; }).AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("Notes", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Notes API", Version = "v1", }); });
解决方案
以下是针对性的排查和解决步骤:
1. 验证EDM模型实体注册
新增控制器对应的实体必须在GetEdmModel()中正确注册,OData依赖EDM模型识别路由,未注册的实体无法生成对应的路由规则。
示例正确的EDM模型配置:
private static IEdmModel GetEdmModel() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); // 实体集名称需与控制器名称匹配(复数形式),或后续显式指定路由 builder.EntitySet<Note>("Values"); return builder.GetEdmModel(); }
2. 显式指定OData路由模板
若控制器名称与实体集名称不匹配,需通过[ODataRoute]属性显式绑定路由:
public class ValuesController : ODataController { [ODataRoute("Values")] [EnableQuery(PageSize = 5)] public IQueryable<Note> Get() { return _context.Notes.AsQueryable(); } }
3. 配置Swagger对OData的支持
默认Swagger无法自动识别OData路由,需添加专门的支持包并配置:
- 安装NuGet包:
Install-Package Swashbuckle.AspNetCore.OData
- 修改Swagger服务配置:
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("Notes", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Notes API", Version = "v1" }); }); // 添加OData的Swagger扩展支持 builder.Services.AddSwaggerGenOData(opt => { opt.ModelFilter<ODataModelFilter>(); });
- 调整中间件顺序(确保OData路由先于Swagger加载):
app.UseRouting(); app.UseAuthorization(); // 先注册OData端点 app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.EnableDependencyInjection(); endpoints.Select().Expand().Filter().OrderBy().Count().MaxTop(100); }); // 再注册Swagger中间件 app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/Notes/swagger.json", "Notes API V1"); });
4. 遵循OData控制器命名约定
OData默认使用实体集名称匹配控制器的复数形式:
- 实体集为
Notes→ 控制器命名为NotesController - 实体集为
Values→ 控制器命名为ValuesController
不遵循此约定时,必须显式指定路由模板。
5. 修正路由前缀配置
若移除了MetadataRoutingConvention,可通过AddRouteComponents指定全局路由前缀,确保路由可被正确识别:
opt.AddRouteComponents("api", GetEdmModel()) // 添加全局前缀"api" .Select() .Expand() .Count() .Filter() .OrderBy().SetMaxTop(100).TimeZone = TimeZoneInfo.Utc;
此时控制器访问路径为/api/Values。
内容的提问来源于stack exchange,提问作者suresh reddy
相关产品推荐
相关产品推荐

