【发布时间】:2021-10-20 04:20:18
【问题描述】:
我遇到的问题与其他与 Swagger UI 中多个 API 文档有关的问题略有不同。
我按预期生成了两个 .json 文档,并且 UI 右上角的下拉菜单允许我在 v1 文档和 v2 文档之间切换。
这是我的问题: v1 文档显示 v1 API 的一个可用操作。但是,v2 文档显示了 v1 和 v2 的可用操作。
这是我的startup.cs 文件中的完整代码:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using netCoreV3_1ApiStarter.Entities;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Versioning;
namespace netCoreV3_1ApiStarter
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
#region API Versioning
services.AddApiVersioning(c =>
{
c.DefaultApiVersion = new ApiVersion(1, 0);
c.AssumeDefaultVersionWhenUnspecified = true;
c.ReportApiVersions = true;
c.ApiVersionReader = new UrlSegmentApiVersionReader();
});
#endregion
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = $"{Configuration.GetSection("ApplicationName").Value} API",
Version = "v1",
Description = $"API v1 methods available for the {Configuration.GetSection("ApplicationName").Value} system",
Contact = new OpenApiContact
{
Email = "blah@blah.com",
Name = "Nunya",
Url = new System.Uri("http://www.apple.com")
}
});
c.SwaggerDoc("v2", new OpenApiInfo
{
Title = $"{Configuration.GetSection("ApplicationName").Value} API",
Version = "v2",
Description = $"API v2 methods available for the {Configuration.GetSection("ApplicationName").Value} system",
Contact = new OpenApiContact
{
Email = "blah@blah.com",
Name = "Nunya",
Url = new System.Uri("http://www.apple.com")
}
});
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.DocInclusionPredicate((docName, apiDesc) => apiDesc.GroupName == docName);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", $"{Configuration.GetSection("ApplicationName").Value} API v1");
c.SwaggerEndpoint("/swagger/v2/swagger.json", $"{Configuration.GetSection("ApplicationName").Value} API v2");
c.RoutePrefix = string.Empty;
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
我将我的控制器按 API 版本分隔到子文件夹中,以尝试组织和防止命名空间冲突等。
v1 WeatherForecastController.cs 文件:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
namespace netCoreV3_1ApiStarter.Controllers.v1
{
[ApiVersion("1.0")]
[ApiExplorerSettings(GroupName = "v1")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
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();
}
}
}
还有,我的 v2 WeatherForecastController.cs:
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
namespace netCoreV3_1ApiStarter.Controllers.v2
{
[ApiVersion("2.0")]
[ApiExplorerSettings(GroupName = "v2")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
// GET: api/<WeatherForecastController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<WeatherForecastController>/5
[HttpGet("{id}")]
public string Get(int id)
{
return $"API v2 {id}";
}
// POST api/<WeatherForecastController>
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/<WeatherForecastController>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<WeatherForecastController>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
关于让 v1 屏幕显示可用 v1 操作和 v2 屏幕显示可用 v2 操作的任何建议?
编辑 10/21/2021: 修复了第二个 SwaggerDoc 对象定义中的错字。当它应该引用 v2 时错误地引用了 v1。但是,性能没有差异。
【问题讨论】:
-
您在两次调用 c.SwaggerDoc 时都有“Version = "v1"",不确定它是否有影响。
-
@Oscar 是的,这是一个错字。不幸的是,仍然没有改变行为。
标签: c# asp.net-core swagger