在单个控制器上对api版本支持生成的Swagger Doc问题

时间:2017-06-27 08:07:40

标签: asp.net asp.net-web-api swagger swashbuckle api-versioning

我有两个由Swashbuckle生成的Swagger文档,即docs / v1和docs / v2。但是,docs / v2并未提供有关GetV2()操作的信息。如果Swashbuckle有解决此问题的选项,请提供帮助。

1.由于路径模板对于动作get()和getv2()似乎相同,因此docs v2不会显示有关getV2()的任何信息。

2。 Swagger定义看起来不像v1.0 / get,而在文档/ v1中显示为v {version} / get

注意:我已经提到了派送样品,但不确定我错过了什么。当我使用Swashbuckle时,所有样本都参考Swashbuckle.core。

[ApiVersion("1.0")] 
[ApiVersion("2.0")]
public class HelloController : ApiControllerBase
{
    [MapToApiVersion("1.0")]
    [Route("v{version:apiVersion}/get")]
    [HttpGet]
    public ProjectSightActionResult Get()
    {
        return new Ok("Version 1.0");
    }

    [MapToApiVersion("2.0")]
    [Route("v{version:apiVersion}/get")]
    [HttpGet]
    public ProjectSightActionResult GetV2()
    {
        return new Ok("Version 2.0");
    }
}

这是我的控制器,包括两个动作,一个用于版本v1,另一个用于v2。以下是路径约束的webapi.config:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services

    // Version Start 
    // https://github.com/Microsoft/aspnet-api-versioning/wiki/Versioning-via-the-URL-Path
    // added to the web api configuration in the application setup
    var constraintResolver = new DefaultInlineConstraintResolver()
    {
        ConstraintMap = {["apiVersion"] = typeof( ApiVersionRouteConstraint )}
    };

    config.MapHttpAttributeRoutes(constraintResolver);
    config.AddApiVersioning();
    // Version End 

    // Web API routes
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
    config.Filters.Add(new AuthenticationFilter());


    // This causes Web API to remove the IPrincipal from any request that enters the Web API pipeline. Effectively, it "un-authenticates" the request. 
    // https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-filters
    config.SuppressHostPrincipal();
}

我的Swagger配置包含代码:

[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace sample.WebAPI
{
    public class SwaggerConfig
    {
        public static void Register()
        {
            var thisAssembly = typeof(SwaggerConfig).Assembly;

             GlobalConfiguration.Configuration
                .EnableSwagger(c =>
                    {
                    c.MultipleApiVersions(
                        (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
                               vc =>
                                 {
                                     vc.Version("v1", "sample.WebAPI");
                                     vc.Version("v2", "sample.WebAPI");
                                 });
                    }
                )
                .EnableSwaggerUi(c =>
                    {            
                        c.EnableDiscoveryUrlSelector();

                       // If your API supports ApiKey, you can override the default values.
                       // "apiKeyIn" can either be "query" or "header"                                                

                        c.EnableApiKeySupport("x-jwt-assertion", "header");
                      });
        }

        private static string GetXmlCommentsPath()
        {
            return string.Format(@"{0}\bin\XmlComments.xml", AppDomain.CurrentDomain.BaseDirectory);
        } 

        private static bool ResolveVersionSupportByRouteConstraint(ApiDescription apiDesc, string targetApiVersion)
        {
            //check for deprecated versions
            var controllerVersionAttributes = apiDesc.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<ApiVersionAttribute>(true);
            if (!controllerVersionAttributes.Any())
            {
                return true; // include when no attributes are defined
            }

            if (targetApiVersion.StartsWith("v"))
            {
                targetApiVersion = targetApiVersion.Substring(1); // remove the leading "v" in `v{x.x}`
            }

            var apiVersion = ApiVersion.Parse(targetApiVersion);

            var controllerApiVersion = controllerVersionAttributes
                .Where(x => x.Versions.Contains(apiVersion))
                .FirstOrDefault();

            // has a compatible version, now check the action for [MapToApiVersion]
            if (controllerApiVersion != null)
            {
                var actionMapToAttributes = apiDesc.ActionDescriptor.GetCustomAttributes<MapToApiVersionAttribute>(false);
                if (!actionMapToAttributes.Any())
                {
                    return true; // no MapTo attributes matched, then include the action
                }

                if (actionMapToAttributes.Any(x => x.Versions.Contains(apiVersion)))
                {
                    return true; // include mapped action
                }
            }

            return false;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我不确定您是否曾解决过您的问题,但您现在可以使用官方API Explorer进行API版本控制,这使Swagger集成变得简单。您可以看到完整的工作示例here

这是一个应该适合您的简略版本:

static void Register( HttpConfiguration configuration )
{
    var constraintResolver = new DefaultInlineConstraintResolver() { ConstraintMap = { ["apiVersion"] = typeof( ApiVersionRouteConstraint ) } };

    configuration.AddApiVersioning();
    configuration.MapHttpAttributeRoutes( constraintResolver );

    // note: this option is only necessary when versioning by url segment.
    // the SubstitutionFormat property can be used to control the format of the API version
    var apiExplorer = configuration.AddVersionedApiExplorer( options => options.SubstituteApiVersionInUrl = true );

    configuration.EnableSwagger(
                    "{apiVersion}/swagger",
                    swagger =>
                    {
                        // build a swagger document and endpoint for each discovered API version
                        swagger.MultipleApiVersions(
                            ( apiDescription, version ) => apiDescription.GetGroupName() == version,
                            info =>
                            {
                                foreach ( var group in apiExplorer.ApiDescriptions )
                                {
                                    var description = "A sample application with Swagger, Swashbuckle, and API versioning.";

                                    if ( group.IsDeprecated )
                                    {
                                        description += " This API version has been deprecated.";
                                    }

                                    info.Version( group.Name, $"Sample API {group.ApiVersion}" )
                                        .Contact( c => c.Name( "Bill Mei" ).Email( "bill.mei@somewhere.com" ) )
                                        .Description( description )
                                        .License( l => l.Name( "MIT" ).Url( "https://opensource.org/licenses/MIT" ) )
                                        .TermsOfService( "Shareware" );
                                }
                            } );

                        swagger.IncludeXmlComments( XmlCommentsFilePath );
                    } )
                 .EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );
    }
}

static string XmlCommentsFilePath
{
    get
    {
        var basePath = System.AppDomain.CurrentDomain.RelativeSearchPath;
        var fileName = typeof( Startup ).GetTypeInfo().Assembly.GetName().Name + ".xml";
        return Path.Combine( basePath, fileName );
    }
}