It's possible to have multiple document endpoint like in swashbuckle?
options.SwaggerEndpoint("/swagger/v1/swagger.json", "API v1");
options.SwaggerEndpoint("/swagger/v2/swagger.json", "API v2");
If Yes, how to decorate api calls so that some belongs to one versione and some to the other version?
So According to Rico Suter suggestion what I've done it's kinda like that:
ApiVersionAttribute.cs
public class ApiVersionAttribute:Attribute
{
private List<string> _versions = new List<string>();
public List<string> Versions { get { return _versions; } }
public ApiVersionAttribute(string version) {
Versions.Add(version);
}
}
MyApiVersionProcessor.cs
public string Version { get; set; }
public MyApiVersionProcessor(string version)
{
this.Version = version;
}
public new Task<bool> ProcessAsync(OperationProcessorContext context)
{
bool returnValue = true;
var versionAttributes = context.MethodInfo.GetCustomAttributes()
.Concat(context.MethodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes())
.Where(a => a.GetType()
.IsAssignableTo("MapToApiVersionAttribute", TypeNameStyle.Name)
|| a.GetType()
.IsAssignableTo("ApiVersionAttribute", TypeNameStyle.Name)
)
.Select(a => (dynamic)a)
.ToArray();
var versionAttribute = versionAttributes.FirstOrDefault();
if (null == versionAttribute)
{
returnValue = false;
}
else
{
if (ObjectExtensions.HasProperty(versionAttribute, "Versions")
&& Version.Equals(versionAttribute.Versions[0].ToString()))
{
ReplaceApiVersionInPath(context.OperationDescription, versionAttribute.Versions);
}
else {
returnValue = false;
}
}
return Task.FromResult(returnValue);
}
private void ReplaceApiVersionInPath(SwaggerOperationDescription operationDescription,
dynamic versions)
{
operationDescription.Path = operationDescription.Path.Replace("{version:apiVersion}",
versions[0].ToString());
}
}
And in my Global.asax
// NSwag
// https://github.com/RSuter/NSwag/wiki/OwinGlobalAsax#integration
app.UseSwaggerUi(typeof(WebApiApplication).Assembly, new SwaggerUiSettings
{
//TypeNameGenerator = new MyTypeNameGenerator(),
MiddlewareBasePath = "/swagger",
SwaggerRoute = "/swagger/v1/swagger.json",
Version = "1.0.0.0",
// https://github.com/RSuter/NSwag/wiki/Middlewares
OperationProcessors =
{
new MyApiVersionProcessor("v1")
},
PostProcess = document =>
{
document.BasePath = "/";
document.Produces
= new List<string> { "application/json"
, "text/json"
, "text/html"
, "plain/text"
, "application/xml"};
document.Consumes
= document.Produces;
document.Info.Title = "Document V1";
}
});
app.UseSwaggerUi(typeof(WebApiApplication).Assembly, new SwaggerUiSettings
{
//TypeNameGenerator = new MyTypeNameGenerator(),
MiddlewareBasePath = "/swagger",
SwaggerRoute = "/swagger/v2/swagger.json",
Version = "2.0.0.0",
OperationProcessors =
{
new MyApiVersionProcessor("v2")
},
PostProcess = document =>
{
document.BasePath = "/";
document.Produces
= new List<string> { "application/json"
, "text/json"
, "text/html"};
document.Consumes
= document.Produces;
document.Info.Title = "Document V2";
}
});
And decorated my Controllers' Methods with
[ApiVersion("v2")]
[ApiVersion("v1")]
etc.