首页 文章

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

提问于
浏览
0

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

1.Since the route template appears to be same for actions get() and getv2(), docs v2 doesn't show any info about getV2().

2. Swagger definition doesn't look v1.0/get while appears as v/get in docs/v1

注意:我已经提到了apiversioning样本,但不知道我错过了什么 . 当我使用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 回答

  • 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 );
        }
    }
    

相关问题