.net core .Net core 2.2 API版本控制和正确路由
我正在创建一个API。我使用swagger,但由于有大量的控制器和操作,我想按域划分API端点。为此,我考虑了API的版本控制。我考虑过使用ApiVersion的状态。我的控制器代码如下.net core .Net core 2.2 API版本控制和正确路由,.net-core,routes,swagger,versioning,swashbuckle,.net Core,Routes,Swagger,Versioning,Swashbuckle,我正在创建一个API。我使用swagger,但由于有大量的控制器和操作,我想按域划分API端点。为此,我考虑了API的版本控制。我考虑过使用ApiVersion的状态。我的控制器代码如下 [ApiVersion("1.0-First")] //This is ApiVersion MajorVersion = 1, Status = "First" [Route("api/v{version:apiVersion}/[controller]&qu
[ApiVersion("1.0-First")] //This is ApiVersion MajorVersion = 1, Status = "First"
[Route("api/v{version:apiVersion}/[controller]")]
public class FirstController
[ApiVersion("1.0-Second")]
[Route("api/v{version:apiVersion}/other")]
public class SecondController
我的招摇过市看起来很好,API部分的定义也很好。(我知道path应该没有大写字母-这仅用于测试目的)
但昂首阔步无法到达任何终点。因为有效端点位于/api/v1.0-First/First而不是/api/v1/First。我的startUp类如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore().AddApiExplorer();
services.AddApiVersioning(c =>
{
c.ApiVersionReader = ApiVersionReader.Combine(
new QueryStringApiVersionReader("V"),
new UrlSegmentApiVersionReader());
c.ReportApiVersions = false;
c.DefaultApiVersion = new ApiVersion(1, 0);
});
services.AddVersionedApiExplorer(options =>
{
options.SubstituteApiVersionInUrl = true;
options.SubstitutionFormat = "V";
options.DefaultApiVersion = new ApiVersion(1, 0);
});
services.RegisterSwaggerConfiguration();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseMvc();
app.AddSwagger(app.ApplicationServices.GetService<IApiVersionDescriptionProvider>(), Configuration);
}
public void配置服务(IServiceCollection服务)
{
services.AddMvcCore().AddApiExplorer();
services.addapVersioning(c=>
{
c、 ApiVersionReader=ApiVersionReader.Combine(
新QueryStringApersionReader(“V”),
新的URLSectionApiversionReader());
c、 ReportApiVersions=false;
c、 DefaultApiVersion=新的ApiVersion(1,0);
});
services.AddVersionedApiExplorer(选项=>
{
options.substituteApprovisionInUrl=true;
options.SubstitutionFormat=“V”;
options.DefaultApiVersion=新的ApiVersion(1,0);
});
services.RegisterSwagerConfiguration();
}
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseMvc();
app.AddSwagger(app.ApplicationServices.GetService(),配置);
}
我编写了一些静态类来添加基于IApiVersionDescriptionProvider的依赖项
public static class SwaggerExtension
{
public static void RegisterSwaggerConfiguration(this IServiceCollection services)
{
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen();
}
public static void AddSwagger(this IApplicationBuilder app, IApiVersionDescriptionProvider provider, IConfiguration configuration)
{
var prefix = "swagger";
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.RoutePrefix = string.Empty;
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"{prefix}/{description.GroupName}/swagger.json", description.GroupName);
}
});
}
}
公共静态类扩展
{
公共静态无效注册表WaggerConfiguration(此IServiceCollection服务)
{
services.AddTransient();
services.addswagggen();
}
公共静态void AddSwagger(此IAApplicationBuilder应用程序、IApiVersionDescriptionProvider提供程序、IConfiguration配置)
{
var prefix=“招摇过市”;
app.UseSwagger();
app.UseSwaggerUI(c=>
{
c、 RoutePrefix=string.Empty;
foreach(provider.ApiVersionDescriptions中的变量描述)
{
c、 swagger端点($“{prefix}/{description.GroupName}/swagger.json”,description.GroupName);
}
});
}
}
和另一个用于生成SwaggerDoc的类
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider provider;
private readonly IConfiguration configuration;
public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider, IConfiguration configuration)
{
this.provider = provider;
this.configuration = configuration;
}
public void Configure(SwaggerGenOptions options)
{
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
}
}
private OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
{
var info = new OpenApiInfo()
{
Title = description.GroupName,
Version = description.ApiVersion.ToString(),
};
if (description.IsDeprecated)
{
info.Description += " This API version has been deprecated.";
}
return info;
}
}
public类配置swagger选项:IConfigureOptions
{
私有只读IApiVersionDescriptionProvider;
专用只读IConfiguration配置;
公共配置Swagger选项(IApiVersionDescriptionProvider提供程序、IConfiguration配置)
{
this.provider=提供者;
this.configuration=配置;
}
公共void配置(招摇过市选项)
{
foreach(provider.ApiVersionDescriptions中的变量描述)
{
options.SwaggerDoc(description.GroupName,CreateInfoForApiVersion(description));
}
}
私有OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription描述)
{
var info=new openapinfo()
{
Title=description.GroupName,
Version=description.apivision.ToString(),
};
如果(说明已说明)
{
info.Description+=“此API版本已被弃用。”;
}
退货信息;
}
}
我希望以api/v1/First或api/v1.0/First的形式获得路由工作(这应该无关紧要)。也许编写一些自定义中间件来处理这种情况是个好主意?
到目前为止,我已经没有想法了,一般来说,我找不到任何关于ApiVersion使用状态的文章。
编辑:
更改了标题。不久前我们遇到了类似的问题。我们需要按客户权限/域划分Api。研究也花了一些时间:),请注意,我们正在使用NSwag 正如您已经提到的(自定义中间件),我们已经创建了一个自定义OperationProcessor并使用了基类型检查。请看一个例子:
services.AddOpenApiDocument(document =>
{
document.Title = "API A";
document.OperationProcessors.Insert(0, new IncludeAApiControllersInSwagger());
});
services.AddOpenApiDocument(document =>
{
document.Title = "API B";
document.OperationProcessors.Insert(0, new IncludeBApiControllersInSwagger());
});
然后
private class IncludeAApiControllersInSwagger : IOperationProcessor
{
public bool Process(OperationProcessorContext context)
{
return IsControllerInType(context, typeof(AApiController));
}
}
private class IncludeBApiControllersInSwagger : IOperationProcessor
{
public bool Process(OperationProcessorContext context)
{
return IsControllerInType(context, typeof(BApiController));
}
}
最后一步是在控制器上构建适当的继承