开发者社区> 殷慈航> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

4.C#WebAPI多版本管理介绍及实现方案详解

简介: 1.什么是 API 的多版本? 说白了就是多版本共存的问题。为方便大家理解我就举个例子吧,大家想必都用过Jquery吧,它的1.*版本做到了对低版本IE的支持;2.*版本还保留着ajax,但是不再支持老旧浏览器;3.*版本连ajax都不留了;但是用户不会升级、用户拒绝升级等原因,造成这些旧版本也需要运行,但是新版却已经修改了规范与旧版旧版冲突了。
+关注继续查看

1.什么是 API 的多版本?

说白了就是多版本共存的问题。为方便大家理解我就举个例子吧,大家想必都用过Jquery吧,它的1.*版本做到了对低版本IE的支持;2.*版本还保留着ajax,但是不再支持老旧浏览器;3.*版本连ajax都不留了;但是用户不会升级、用户拒绝升级等原因,造成这些旧版本也需要运行,但是新版却已经修改了规范与旧版旧版冲突了。造成这些旧版本也需要运行使用。再例如我们手机有Android4.0、5.0、6.0、7.0、8.0或IOS8.0、9.0、10、11同时存在于市场也是类似的。

2.出现多版本问题我们通常的做法

旧版接口做成一个分支,除了进行 bug 修改外,旧版本接口不再做改动;新接口代码继续演化升级。在客户端请求的时候带着要请求的接口版本号,在服务器端选择合适的版本代码进行处理。

3.技术处理方案

(1)(最推荐)不同版本用不同的域名:v1.api.jiyuwu.com、v2.api.jiyuwu.com、v3……。

(2) 在url、报文头等中带不同的版本信息,用 Nginx 等做反向代理服务器,然后将 http://api.jiyuwu.com/api/V1/Login/1和http://api.jiyuwu.com/api/V2/Login/1转到不同的服务器处理。

(3) 多 个 版 本 的 Controller 共 处 在 一 个 项 目 中 , 然 后 使 用 [RoutePrefix] 或 者 IHttpControllerSelector 根据报文头、路径等选择不同的 Controller 执行。下面主要讲这两种方法。

4.针对3.(3)的两种方案的案例

 (1)[RoutePrefix] 案例

旧版保持原样不改变

public class LoginController : ApiController
    {
        [HttpGet]
        public string ToLogin(int id)
        {
            return "这是旧版" + id;
        }

    }
View Code

新版代码同时用路由处理

[RoutePrefix("api/V2/Login")]
    public class LoginV2Controller : ApiController
    {
        [Route("{id}")]
        [HttpGet]
        public string ToLogin(int id)
        {
            return "这是新版" + id;
        }
    }
View Code

(2) IHttpControllerSelector 案例

项目结构如图

(1)添加VersionnControllerSelector类

public class VersionnControllerSelector : DefaultHttpControllerSelector
    {
        public HttpConfiguration _config;

        public VersionnControllerSelector(HttpConfiguration config)
            : base(config)
        {
            _config = config;
        }
        public override IDictionary<string, System.Web.Http.Controllers.HttpControllerDescriptor> GetControllerMapping()
        {
            Dictionary<string, HttpControllerDescriptor> dic = new Dictionary<string, HttpControllerDescriptor>();
            foreach (var ams in _config.Services.GetAssembliesResolver().GetAssemblies())
            {
                //获取继承自ApiControl的非抽象类
                var controlTypes = ams.GetTypes().Where(p => !p.IsAbstract && typeof(ApiController).IsAssignableFrom(p)).ToArray();
                foreach (var ctrlType in controlTypes)
                {
                    //从namespace中提取出版本号
                    var match = Regex.Match(ctrlType.Namespace,
                    @"MoreVersionContorl.Controllers.V(\d+)");
                    if (match.Success)
                    {
                        string verNum = match.Groups[1].Value;//获取版本号
                        string ctrlName =
                        Regex.Match(ctrlType.Name, "(.+)Controller").Groups[1].Value;//从LoginController中拿到Login
                        string key = ctrlName + "V" + verNum;//Personv2为key
                        dic[key] = new HttpControllerDescriptor(_config, ctrlName, ctrlType);
                    }
                }
            }
            return dic;
        }
        public override System.Web.Http.Controllers.HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            //获取所有Controller集合
            var controllers = GetControllerMapping();
            //获取路由数据
            var routeData = request.GetRouteData();
            //从路由中获取当前controller的名称
            var controllerName = (string)routeData.Values["controller"];
            //从url中获取到版本号
            string verNum =
            Regex.Match(request.RequestUri.PathAndQuery, @"api/V(\d+)").Groups[1].Value;
            string key = controllerName + "V" + verNum;//获取Loginv2
            if (controllers.ContainsKey(key))//获取HttpControllerDescriptor
            {
                return controllers[key];
            }
            else
            {
                return null;
            }
        }
    }
View Code

(2)创建V1和V2下的两个控制器

1) V1下的LoginController

 public class LoginController : ApiController
    {
        public string Get(int id)
        {
            return "This Version is V1,id=" + id;
        }
    }
View Code

2) V2下的LoginController

public class LoginController : ApiController
    {
        public string Get(int id)
        {
            return "This Version is V2,id="+id;
        }
    }
View Code

(3)修改WebApiConfig

public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务

            // Web API 路由
            config.MapHttpAttributeRoutes();

            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);
            config.Routes.MapHttpRoute(
            name: "DefaultApiV1",
            routeTemplate: "api/V1/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );
            config.Routes.MapHttpRoute(
            name: "DefaultApiV2",
            routeTemplate: "api/V2/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );
            config.Services.Replace(typeof(IHttpControllerSelector),
            new VersionnControllerSelector(config));
        }
View Code

(4)配置完毕请求结果如图:

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
web文本划线的极简实现
web文本划线的极简实现
42 0
React.js中JSX的原理与关键实现
在开始开发之前,我们需要创建一个空项目文件夹
22 0
各版本 web-app 标签
IDEA 中创建 Maven 项目默认就使用最低版本的 web-app 2.3,据说是为了扩展性,于是导致使用过程中遇到一系列问题,比如:web-app标签中子标签顺序规范问题、JSP 中默认不支持 EL 表达式问题等,于是整理了如下 web-app 的版本。
43 0
2021最新版BAT大厂Netty面试题集(有详尽答案)
2021最新版BAT大厂Netty面试题集(有详尽答案)
48 0
ABAP development tools实现原理介绍
ABAP development tools实现原理介绍
45 0
视觉智能开放平台与Serverless工作流深度合作实现API调用的上云托管!
本文介绍如何快速使用 Serverless 工作流 + 阿里云视觉智能开放平台构建人工智能服务应用
896 0
阿里云播放器SDK的正确打开方式 | Aliplayer Web播放器介绍及功能实现(三)
阿里云播放器SDK(ApsaraVideo for Player SDK)是阿里视频云端到云到端服务的重要一环,除了支持点播和直播的基础播放功能外,还深度融合视频云业务,支持视频的加密播放、安全下载、首屏秒开、低延时等业务场景,为用户提供简单、快速、安全、稳定的视频播放服务。
15987 0
日志组件slf4j介绍及配置详解
1 基本介绍 每一个Java程序员都知道日志对于任何一个Java应用程序,尤其是服务端程序是至关重要的,而很多程序员也已经熟悉各种不同的日志库如java.util.logging、Apache log4j、logback。但如果你还不知道SLF4J(Simple logging facade for Java)的话,那么是时候去在你项目中学习使用SLF4J了。 SLF4J
4043 0
三种主流的Web服务实现方案(REST+SOAP+XML-RPC)简述及比较
目前知道的三种主流的Web服务实现方案为:REST:表象化状态转变 (软件架构风格)SOAP:简单对象访问协议 XML-RPC:远程过程调用协议 下面分别作简单介绍: REST:表征状态转移(Representational State Transfer),采用Web 服务使用标准的 HTTP 方法 (GET/PUT/POST/DELETE) 将所有 Web 系统的服务抽象为资源,REST从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表征。
798 0
+关注
殷慈航
即来即用,拿来主义!专业就是让复杂的事物变简单!---机遇屋
11
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载