webapi版本控制

2021-07-19 23:18

阅读:448

一、为什么要使用版本控制

(1)项目不停迭代,在增加新接口时不破坏原有接口,以保证webapi推出新功能后旧的移动客户端可顺利使用老接口

(2)限制移动端对接口的访问,为客户端提供额外的功能。

二、webapi版本控制方法

(1)在 URL 中追加版本或作为查询字符串参数

(2)通过自定义标头和通过接受标头

三、webapi版本控制实现

微软有开源的组件库,不用重复造轮子,aspnet-api-versioning

四、swagger查看各个版本的webapi

 1.如何使用swagger来查看webapi文档,请参阅我的另一篇文章

swagger集成

2.如何查看不同版本有哪些接口,效果如下

技术分享图片

 

技术分享图片

 

 我的版本控制方法基于Header实现,使用的是asp.net mvc,主要的代码已加粗

Startup.cs

public class Startup
    {
        public static string VersionName = "api-version";
        /// 
        /// Configures the application using the provided builder.
        /// 
        /// The current application builder.
        public void Configuration( IAppBuilder builder )
        {
            // we only need to change the default constraint resolver for services that want urls with versioning like: ~/v{version}/{controller}
            var constraintResolver = new DefaultInlineConstraintResolver() { ConstraintMap = { ["apiVersion"] = typeof( ApiVersionRouteConstraint ) } };
            var configuration = new HttpConfiguration();
            var httpServer = new HttpServer( configuration );

            // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
            configuration.AddApiVersioning( o => {
                o.ReportApiVersions = true;
                //采用header方式控制版本
                o.ApiVersionReader = new HeaderApiVersionReader(Startup.VersionName);
            } );
            configuration.MapHttpAttributeRoutes( constraintResolver );
            //集成swagger
            var apiExplorer = configuration.AddVersionedApiExplorer( o => o.GroupNameFormat = "‘v‘VVV" );
            configuration.EnableSwagger(
                            "{apiVersion}/swagger",
                            swagger =>
                            {
                                //多版本选择配置
                                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, $"webapi文档 {group.ApiVersion}");
                                        }
                                    } );
                                //调试时添加版本参数
                                swagger.DocumentFilter();
                                //为版本参数设置默认值
                                swagger.OperationFilter();
                                //载入xml
                                string xmlFile = XmlCommentsFilePath;
                                swagger.IncludeXmlComments(xmlFile);
                            } )
                         .EnableSwaggerUi( swagger => {
                             swagger.EnableDiscoveryUrlSelector();
                         });

            builder.UseWebApi( httpServer );
        }

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

 

 

ReplaceQueryVersionFilter.cs

 /// 
    /// 将query中的版本号参数更换为head请求方式
    /// 
    public class ReplaceQueryVersionFilter : IDocumentFilter
    {
        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
        {
            foreach (PathItem path in swaggerDoc.paths.Values)
            {
                var versionParam = path.get.parameters.FirstOrDefault(i => i.name == Startup.VersionName);
                if (versionParam != null)
                {
                    var index = path.get.parameters.IndexOf(versionParam);
                    path.get.parameters[index].@in = "header";
                }
            }
        }
    }

 

SwaggerDefaultValuesFilter.cs

public class SwaggerDefaultValuesFilter : IOperationFilter
    {
        /// 
        /// Applies the filter to the specified operation using the given context.
        /// 
        /// The operation to apply the filter to.
        /// The API schema registry.
        /// The API description being filtered.
        public void Apply( Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription )
        {
            if ( operation.parameters == null )
            {
                return;
            }

            foreach ( var parameter in operation.parameters )
            {
                try
                {
                    var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.name);

                    // REF: https://github.com/domaindrivendev/Swashbuckle/issues/1101
                    if (parameter.description == null)
                    {
                        parameter.description = description.Documentation;
                    }

                    // REF: https://github.com/domaindrivendev/Swashbuckle/issues/1089
                    // REF: https://github.com/domaindrivendev/Swashbuckle/pull/1090
                    if (parameter.@default == null)
                    {
                        parameter.@default = description.ParameterDescriptor.DefaultValue;
                    }
                }
                catch
                {

                }
            }
        }
    }

 


评论


亲,登录后才可以留言!