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

新版代码同时用路由处理

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

(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[].Value;//获取版本号
string ctrlName =
Regex.Match(ctrlType.Name, "(.+)Controller").Groups[].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[].Value;
string key = controllerName + "V" + verNum;//获取Loginv2
if (controllers.ContainsKey(key))//获取HttpControllerDescriptor
{
return controllers[key];
}
else
{
return null;
}
}
}

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

1) V1下的LoginController

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

2) V2下的LoginController

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

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

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

4.C#WebAPI多版本管理介绍及实现方案详解的更多相关文章

  1. web标准 浏览器介绍 开发工具介绍 HTML介绍 HTML颜色介绍 规范 HTML结构详解 {前端之前端初识}

    前端之前端初识   前端初识 本节目录 一 web标准 二 浏览器介绍 三 开发工具介绍 四 HTML介绍 五 HTML颜色介绍 六 规范 七 HTML结构详解 一 web标准 web准备介绍: 1. ...

  2. Solr系列三:solr索引详解(Schema介绍、字段定义详解、Schema API 介绍)

    一.Schema介绍 1. Schema 是什么? Schema:模式,是集合/内核中字段的定义,让solr知道集合/内核包含哪些字段.字段的数据类型.字段该索引存储. 2. Schema 的定义方式 ...

  3. php strpos() 函数介绍与使用方法详解

    本文主要和大家介绍PHP中mb_strpos的使用技巧,通过使用语法以及实例给大家详细分析了用法,需要的朋友参考学习下.希望能帮助到大家.mb_strpos(PHP 4 >= 4.0.6, PH ...

  4. JMS学习(二)- JMS Message Model 组成介绍及消息头详解

    一.前言 从本文起依次详细介绍JMS中的一些重要的概念,主要参考了官方的JMS1.1的文档,该文档很老了,是02年的,那年,JAVA还没有被Oracle收购..本文主要介绍Message及其相关概念, ...

  5. (2)Spring集成Quartz定时任务框架介绍和Cron表达式详解

    在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但 ...

  6. Spring集成Quartz定时任务框架介绍和Cron表达式详解

    原文地址:http://www.cnblogs.com/obullxl/archive/2011/07/10/spring-quartz-cron-integration.html 在JavaEE系统 ...

  7. 接口测试——httpclient介绍与请求方式详解

    httpClient工具介绍 HTTP协议可能是现在lntemet上使用得最多.最重要的协议了,越来越多的Java应用程序需要直接通过HTTP协议来访问网络资源.虽然在JDK的java.net包中已经 ...

  8. JAR包介绍大全用途作用详解JAVA

    jta.jar 标准JTA API必要commons-collections.jar 集合类 必要antlr.jar  ANother Tool for Language Recognition 必要 ...

  9. Nginx的介绍以及编译安装详解

    Nginx的介绍以及编译安装详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Nginx(全称”engine x“)诞生背景 apache主要优点是功能丰富且足够稳定,但是其 ...

随机推荐

  1. 关于元表,self,元方法__index

    这是需要仔细分辨的几个概念. 元表:相当于table的隐藏属性. 只有固定的一些方法,如__index,__tostring,__add等,称为元方法. 虽然是固定的,但是任何table都可以作为任何 ...

  2. php 利用http上传协议(表单提交上传图片 )

    主要就是利用php 的 fsocketopen 消息传输. 这里先通过upload.html 文件提交,利用chrome抓包,可以看到几个关键的信息. 首先指定了表单类型为multipart/form ...

  3. Html的Padding,Margin自己理解图

    Html的Padding,Margin自己理解图.

  4. Python高级用法篇——笔记

    1.Python3字典中items()和python2.x中iteritems()的区别 在Python2.x中,items( )用于 返回一个字典的拷贝列表[Returns a copy of th ...

  5. PAT 1073 多选题常见计分法(20)(代码+思路)

    1073 多选题常见计分法(20 分) 批改多选题是比较麻烦的事情,有很多不同的计分方法.有一种最常见的计分方法是:如果考生选择了部分正确选项,并且没有选择任何错误选项,则得到 50% 分数:如果考生 ...

  6. c++ tricks

    1 关于virtual关键字的实验 1.1 在派生类中改变virtual函数访问权限 定义两个类A,B,其中B公有派生于A.A中定义一个private成员虚函数func,B中覆写此函数,但是将其访问权 ...

  7. 值得一看!2018年最优秀的9个Android Material Design Apps!

    今年4月,谷歌Gmail推出了全新的设计外观,全新的配色方案,更多的空白区域和精致的图标.也带来了Material Design 的一些改变 – Material Theming (材料主题),旨在自 ...

  8. abp 的坑

    多数据库连接问题 viewmodel的验证问题 发布后,一段查找sln查找代码无法适用生产环境问题 多语言问题,默认中文设置与模板配置文件不统一

  9. servlet 中 service ,doGet , doPost 关系

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2 ...

  10. 2018.09.29 bzoj3156: 防御准备(斜率优化dp)

    传送门 斜率dp经典题目. 然而算斜率的时候并没有注意到下标的平方会爆int于是咕咕*2. 这道题我用了两个数组来表示状态. f[i]f[i]f[i]表示最后i个位置倒数第i个放木偶的最优值. g[i ...