1

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

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

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

注意:我参考了 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;
        }
    }
}
4

1 回答 1

1

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

这是一个适合您的精简版本:

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 );
    }
}
于 2018-03-26T02:21:27.963 回答