1.多版本管理概念

什么是API的多版本问题?Android等App存在着多版本客户端共存的问题:由于早期没有内置升级机制,用户不会升级,拒绝升级等原因,造成了许多软件的旧版本App也在运行。开发新版本App时,要给接口增加新的功能或者修改以前接口的规范,会造成旧版本App无法使用,因此再一定情况下会“保留旧接口的运行,新功能用新接口”,这样就会存在多版本接口共存的问题。

2.解决方式

1.不同版本用不同的域名:v1.api.rsfy.com、v2.api.rsfy.com、v3……;

2.在Url,报文头等中带不同的版本信息,用Nginx等做反向代理服务,然后将 http://api.rsfy.com/api/v1/User/1http://api.rsfy.com/api/v2/User/1 转到不同的服务器处理

3.多个版本的Controller共处在一个项目中,然后使用[RoutePrefix]或者IHttpControllerSelector根据报文头,路径等选择不同的Controller执行

下面以第三个种记录一个例子

3.解决例题

创建一个WebApi项目,在Controllers中创建各个版本的目录

然后我们在每个版本下创建一个Home控制器

  1. public class HomeController : ApiController
  2. {
  3. [HttpGet]
  4. public String GetIndex()
  5. {
  6. return "这是v1版本的Index";
  7. }
  8. }
  1. public class HomeController : ApiController
  2. {
  3. [HttpGet]
  4. public String GetIndex()
  5. {
  6. return "这是v2版本的Index";
  7. }
  8. }

正常情况下,我们是不可以在Controllers中创建目录的,这不符合约定,所以我们必须改写其中代码,让其根据我们需求来选择控制器。

下面我们创建一个我们自己的IHttpControllerSelector的实现类来替换默认的IHttpControllerSelector。

  1. /// <summary>
  2. /// 自己实现IHttpControllerSelector来替换默认IHttpConllerSelector
  3. /// </summary>
  4. public class VersionConstrollerSelector : IHttpControllerSelector
  5. {
  6. private readonly HttpConfiguration _conf;
  7. public VersionConstrollerSelector(HttpConfiguration configuration)
  8. {
  9. _conf = configuration;
  10. }
  11.  
  12. public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
  13. {
  14. throw new NotImplementedException();
  15. }
  16.  
  17. public HttpControllerDescriptor SelectController(HttpRequestMessage request)
  18. {
  19. throw new NotImplementedException();
  20. }
  21. }

IHttpControllerSelector接口有两个方法,

GetControllerMapping():获取程序中所有的Api接口

SelectController(HttpRequestMessage request):匹配请求的路由

下面我们来重写这两个方法

  1. /// <summary>
  2. /// 获取所有Controller
  3. /// </summary>
  4. /// <returns></returns>
  5. public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
  6. {
  7. Dictionary<String, HttpControllerDescriptor> dict = new Dictionary<string, HttpControllerDescriptor>();
  8. foreach (var item in _conf.Services.GetAssembliesResolver().GetAssemblies())
  9. {//循环所有程序集
  10. //获取所有继承自ApiController的非抽象类
  11. var controllerTypes = item.GetTypes()
  12. .Where(y => !y.IsAbstract && typeof(ApiController)
  13. .IsAssignableFrom(y)).ToArray();
  14. foreach (var ctrlType in controllerTypes)
  15. {//循环程序集中类型
  16. //从namespace中提取出版本号
  17. var match = Regex.Match(ctrlType.Namespace,GetType().Namespace+ @".Controllers.v(\d+)");
  18. if(match.Success)
  19. {//匹配成功
  20. //获取版本号
  21. string verNum = match.Groups[].Value;
  22. //从控制器总名称中拿到控制器名称(例: HomeController中获取Home)
  23. string ctrlName = Regex.Match(ctrlType.Name, "(.+)Controller").Groups[].Value;
  24. //声明集合中的键
  25. String key = (ctrlName + "v" + verNum).ToLower();
  26. //存储集合值(控制器信息)
  27. dict[key] = new HttpControllerDescriptor(_conf, ctrlName, ctrlType);
  28. }
  29. }
  30. }
  31. return dict;
  32. }
  33. /// <summary>
  34. /// 进行匹配Controller
  35. /// </summary>
  36. /// <param name="request">http请求信息</param>
  37. /// <returns>匹配成功返回控制器信息,匹配失败返回null</returns>
  38. public HttpControllerDescriptor SelectController(HttpRequestMessage request)
  39. {
  40. //获取所有的Controller集合
  41. var controllers = GetControllerMapping();
  42. //获取路由数据
  43. var routeData = request.GetRouteData();
  44. //从路由中获取当前controller的名称
  45. var controllerName = routeData.Values["Controller"] as String;
  46. //如果请求头中存在ApiVerson信息则总其中获取版本号否则从url中获取版本号
  47. var verNum = request.Headers.TryGetValues("ApiVerson", out var versions) ?
  48. versions.Single() :
  49. Regex.Match(request.RequestUri.PathAndQuery, @"api/v(\d+)").Groups[].Value;
  50.  
  51. //获取版本号
  52. var key = (controllerName + "v" + verNum).ToLower();//获取Personv2
  53. //返回控制器信息
  54. return controllers.ContainsKey(key) ? controllers[key] : null;
  55.  
  56. }

  现在我们这个类实现完成以后我们便可以在WebApiConfig类中的Register方法中替换原来的IHttpControllerSelector

  1. public static class WebApiConfig
  2. {
  3. public static void Register(HttpConfiguration config)
  4. {
  5. // Web API 配置和服务
  6. //替换HttpControllerSelector
  7. config.Services.Replace(typeof(IHttpControllerSelector), new VersionConstrollerSelector(config));
  8.  
  9. }
  10. }

并且在其方法创建新的路由

  1. public static void Register(HttpConfiguration config)
  2. {// Web API 路由
  3. config.MapHttpAttributeRoutes();
  4. config.Routes.MapHttpRoute(
  5. name: "DefaultApiv1",
  6. routeTemplate: "api/v1/{controller}/{action}/{id}",
  7. defaults: new { id = RouteParameter.Optional });
  8.  
  9. config.Routes.MapHttpRoute(
  10. name: "DefaultApiv2",
  11. routeTemplate: "api/v2/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional }
  12. );
  13. config.Routes.MapHttpRoute(
  14. name: "DefaultApiv3",
  15. routeTemplate: "api/v3/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional }
  16. );
  17. config.Routes.MapHttpRoute(
  18. name: "DefaultApi",
  19. routeTemplate: "api/{controller}/{action}/{id}",
  20. defaults: new { id = RouteParameter.Optional }
  21. );
  22. }

至此,我们便成功的以替换IHttpControllerSelector方式来完成了多版本管理

WebApi的多版本管理的更多相关文章

  1. Web API的参数、多版本和Filter

    一.关于API的参数a) Web API在WebApiConfig.cs中配置了路由模板,默认为"api/{controller}/{id}",这与MVC路由模板的区别在于没有{a ...

  2. 第十一节:WebApi的版本管理的几种方式

    一. 背景和方案 1. 多版本管理的概念 Android .IOS等 App 存在着多版本客户端共存的问题:App 最新版已经升级到了5.0 了,但是有的用户手机上还运行着 4.8.3.9 甚至2.2 ...

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

    1.什么是 API 的多版本? 说白了就是多版本共存的问题.为方便大家理解我就举个例子吧,大家想必都用过Jquery吧,它的1.*版本做到了对低版本IE的支持:2.*版本还保留着ajax,但是不再支持 ...

  4. WebApi系列(从.Net FrameWork 到 .Net Core)

    一. 简介  1. 什么是WebApi? WebApi是一个很广泛的概念,在这里我们特指.Net平台下的Asp.Net WebApi框架,它是针对各种客户端(浏览器.APP等)来构建Http服务的一个 ...

  5. 基于 Kong 和 Kubernetes 的 WebApi 多版本解决方案

    前言 大家好,很久没有写博客了,最近半年也是比较的忙,所以给关注我的粉丝们道个歉.去年和朱永光大哥聊的时候提了一下我们的这个方案,他说让我有空写篇博客讲一下,之前是非常的忙,所以这次趁着有些时间就写一 ...

  6. ASP.NET Core WebApi版本控制

    前言: 在日常项目开发中,随着项目需求不断的累加.不断的迭代:项目服务接口需要向下兼容历史版本:前些时候就因为Api接口为做版本管理导致接口对低版本兼容处理不友好. 最近就像了解下如何实现WebApi ...

  7. webapi - 使用依赖注入

    本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity:由于快过年这段时间打算 ...

  8. ASP.NET Core MVC/WebAPi 模型绑定探索

    前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...

  9. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

随机推荐

  1. Google Python编程规范

    http://pan.baidu.com/s/1dD1Ra7J 其他语言的编程风格: http://zh-google-styleguide.readthedocs.org/en/latest/

  2. SSH框架的多表查询(方法二)增删查改

     必须声明本文章==>http://www.cnblogs.com/zhu520/p/7773133.html  一:在前一个方法(http://www.cnblogs.com/zhu520/p ...

  3. pyqt5实现注册界面

    __author__ = 'sign_in' import sys from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import * clas ...

  4. PendingIntent、Notification常用方法

    PendingIntent PendingIntent它的直译是:待处理意图,这样翻译,大家就猜出它的作用是什么了,用于处理一些定义但是不立即使用的意图,最常见的就是用户点击通知,然后跳转指定的页面: ...

  5. JavaScript的简单继承实现案例

    <html><body><script> //实现JavaScript继承的步骤: //1:写父类 //2:写子类 //3:用Object.create()来实现继 ...

  6. C++PRIMER 阅读笔记 第三章

    本章主要介绍 string vector 和 bitset, 不能贪多,现在本文主要介绍 string 与 vector 头文件中最好不要使用namespace std, 因为头文件会直接被预处理器放 ...

  7. bootstrap fileinput上传返回400,404,500 等错误替换

    $(".uploadfile").on('filebatchuploaderror', function(event, data, msg) { $(".file-err ...

  8. OpenCASCADE 参数曲线曲面面积

    OpenCASCADE 参数曲线曲面面积 eryar@163.com Abstract. 本文介绍了参数曲面的第一基本公式,并应用曲面的第一基本公式,结合OpenCASCADE中计算多重积分的类,对任 ...

  9. php面试之数据结构和算法

    二.数据结构和算法 1.使对象可以像数组一样进行foreach循环,要求属性必须是私有.(Iterator模式的PHP5实现,写一类实现Iterator接口)(腾讯) <?php class T ...

  10. jQuery选取所有复选框被选中的值并用Ajax异步提交数据

    昨天和朋友做一个后台管理系统项目的时候涉及到复选框批量操作,如果用submit表单提交挺方便的,但是要实现用jQuery结合Ajax异步提交数据就有点麻烦了,因为我之前做过的项目中基本上没用Ajax来 ...