如何在 Swagger 中隐藏 OData 元数据控制器?

How to hide OData Metadata Controller in Swagger?

将我的项目更新到 .NET6 并将 OData 更新到 8.0.4 后,出现了一个具有这些端点的新元数据控制器:

我想以某种方式禁用它或将其从我的服务中删除。

添加OData服务代码:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddControllers(mvcOptions => mvcOptions.EnableEndpointRouting = false)
        .AddOData(opt => opt.AddRouteComponents("", GetEdmModel()).Select().Expand());
}

版本:

我最近遇到了类似的问题。我通过

得到解决方案
  • 从启动文件中删除 odata 服务注入(因为如果我尝试从启动中注入 odata,swagger 会自动添加元数据类)
  • 将 OData 从 8.0.4 降级到 8.0.0
  • 并在控制器内部实现 ODataQueryOptions 而不是 EnableQuery actionfilter
  • 在控制器中使用 ODataBuilder/OdataModelBuilder 而不是启动。在我的例子中是 ODataBuilder

有几个选项可以解决这个问题:

  1. 可以用排除MetadataController
  2. 您可以在 ODataOptions 中使用 Conventions 来删除 MetadataRoutingConvention
  3. 您可以实施 DocumentFilter 以隐藏 MetadataController 和相关模式以防止 Swagger

#2 是最简单的方法:

services
    .AddControllers()
    .AddOData(opt =>
   {
         opt.Conventions.Remove(opt.Conventions.OfType<MetadataRoutingConvention>().First());
         opt.AddRouteComponents("", GetEdmModel()).Select().Expand();
    });

#3 如果您只想隐藏 Swagger 中的 MetadataController 和相关模式:

public class SwaggerODataControllerDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // remove controller
        foreach (ApiDescription apiDescription in context.ApiDescriptions)
        {
            var actionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor;
            if (actionDescriptor.ControllerName == "Metadata")
            {
                swaggerDoc.Paths.Remove($"/{apiDescription.RelativePath}");
            }
        }

        // remove schemas
        foreach ((string key, _) in swaggerDoc.Components.Schemas)
        {
            if (key.Contains("Edm") || key.Contains("OData"))
            {
                swaggerDoc.Components.Schemas.Remove(key);
            }
        }
    }
}

将其添加到 services.AddSwaggerGen:

cfg.DocumentFilter<SwaggerODataControllerDocumentFilter>();

对于选项 #1,您可以这样做:

public class RemoveMetadataControllerFeatureProvider : ControllerFeatureProvider
    {
        protected override bool IsController(TypeInfo typeInfo)
        {
            if (typeInfo.FullName == "Microsoft.AspNetCore.OData.Routing.Controllers.MetadataController")
            {
                // or just compare the name
                return false;
            }

            return base.IsController(typeInfo);
        }
    }

在startup.cs

services.AddControllers()
    .ConfigureApplicationPartManager(manager =>
     {
       manager.FeatureProviders.Remove(manager.FeatureProviders.OfType<ControllerFeatureProvider>().FirstOrDefault());
          manager.FeatureProviders.Add(new RemoveMetadataControllerFeatureProvider());
     }).AddOData(....)