【问题标题】:Odata Controllrer with ODataQueryOptions generates error in swagger : "undefined /swagger/v1/swagger.json"带有 ODataQueryOptions 的 Odata Controllrer 在 swagger 中生成错误:“undefined /swagger/v1/swagger.json”
【发布时间】:2020-05-08 09:35:57
【问题描述】:

我使用的是 net core 3.1。我的项目包含 在启动时配置的 api 控制器(ODataController) UseEndpoints + swagger + odata,

在我将 ODataQueryOptions 添加到控制器中的一种方法之前,一切正常。 之后,swagger 显示以下错误:“undefined /swagger/v1/swagger.json”

这些是我的启动定义:

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddOData();
        services.AddControllers();

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
        });

        SetOutputFormatters(services);
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.EnableDependencyInjection();
            endpoints.Select().Filter().Expand().MaxTop(10);
            endpoints.MapODataRoute("odata", "odata", GetEdmModel());
        });

        app.UseSwagger();

        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
    }

支持 OData 查询的端点。

    [HttpGet]
    [EnableQuery]
    public IEnumerable<WeatherForecast> Get()

    [HttpGet]
    [ODataRoute]
    [EnableQuery(HandleNullPropagation = HandleNullPropagationOption.False, MaxTop = 100, AllowedQueryOptions = AllowedQueryOptions.Select |AllowedQueryOptions.Count)]
    public IEnumerable<WeatherForecast> Getlist(ODataQueryOptions options)

【问题讨论】:

    标签: asp.net-core .net-core


    【解决方案1】:

    这是我的工作演示,你可以参考:

    Startup.cs

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddOData();
            services.AddControllers();
    
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            });
    
            services.AddMvcCore(options =>
            {
                foreach (var outputFormatter in options.OutputFormatters.OfType<ODataOutputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
                {
                    outputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
                }
                foreach (var inputFormatter in options.InputFormatters.OfType<ODataInputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
                {
                    inputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
                }
            });
        }
    
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseHttpsRedirection();
    
            app.UseRouting();
    
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.EnableDependencyInjection();
                endpoints.Select().Filter().Expand().MaxTop(10);
                endpoints.MapODataRoute("odata", "odata", GetEdmModel());
            });
    
            app.UseSwagger();
    
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });
        }
    
        IEdmModel GetEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<WeatherForecast>("WeatherForecast");
            return builder.GetEdmModel();
        }
    

    控制器

    [ApiController]
    [Route("odata/[controller]/[action]")]
    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]
        [EnableQuery]
        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();
        }
    
    
        [HttpGet]
        [ODataRoute]
        [EnableQuery(HandleNullPropagation = HandleNullPropagationOption.False, MaxTop = 100, AllowedQueryOptions = AllowedQueryOptions.Select | AllowedQueryOptions.Count)]
        public IEnumerable<WeatherForecast> Getlist(ODataQueryOptions options)
        { }
    }
    

    【讨论】:

    • 谢谢!似乎成功了,但我有几个问题: 1. 为什么我们需要添加 outputFormatter/inputFormatter ConfigureServices ? 2. 我可以从 OadaController 继承而不是 ControllerBase 吗?
    • @A_G, 1.如果没有在ConfigureServices方法中添加outputFormatter/inputFormatter,在导航到/swagger/v1/swagger.json或者制作调试器时会发现具体错误:InvalidOperationException: No media types found in 'Microsoft.AspNet.OData.Formatter.ODataInputFormatter.SupportedMediaTypes'. Add at least one media type to the list of supported media types.。跨度>
    • 2.如果继承自 ODataController 而不是 ControllerBase,则需要在 ODataController 上添加`[ApiExplorerSettings(IgnoreApi = false)]` 否则会错过swagger UI,参考this known github issue
    • @A_G ,如果您认为我的解决方案有帮助,您可以将我的回复标记为答案吗?这将帮助面临相同或相似问题的其他人快速找到答案。非常感谢!
    • 不幸的是,这个建议并不能完全解决这个问题,因为 swaager 无法识别和显示在 EnableQuery 属性中声明的 AllowedQueryOptions。这是声明 api 的方式: [HttpGet][ProducesResponseType(typeof(ODataValue>), StatusCodes.Status200OK)][ProducesResponseType(StatusCodes.Status404NotFound)] [EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Select)] public IEnumerable Getlist(ODataQueryOptions 选项)
    猜你喜欢
    • 2021-05-31
    • 2019-12-23
    • 2022-01-25
    • 2019-02-09
    • 2020-06-06
    • 2019-07-29
    • 2015-08-06
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多