WebApi多版本控制
常用的解决方案
①不同版本不同域名;
②在url、报文头等中带不同版本信息,用NginX做反向代理服务器,然后将http://api.xx.com/api/v1/Usr/1和http://api.xx.com/api/v2/Usr/1转到不同服务器
③多个版本的controller在一个项目中,然而使用[RoutePrefix]或者IHttpControllerSeletor根据报文头、路径等信息选择不同的Controller执行。
eg:
[RoutePrefix("api/v2/Hoo")] public class HomeController : ApiController { [Route("Get")] public string Get() { return "测试一下"; } } //一旦设置了[RoutePrefix]、[Route],在路由表中的路由就当前Controller失去了管理。
通过自定义ControllerSelector实现多版本管理
1.修改路由

1 config.Routes.MapHttpRoute( 2 name: "DefaultApiv1", 3 routeTemplate: "api/v1/{controller}/{id}", 4 defaults: new { id = RouteParameter.Optional } 5 ); 6 config.Routes.MapHttpRoute( 7 name: "DefaultApiv2", 8 routeTemplate: "api/v2/{controller}/{id}", 9 defaults: new { id = RouteParameter.Optional } 10 );
2.自定义VersionControllerSelector类继承DefaultHttpControllerSelector,重写GetControllerMapping、SelectController

1 public class VersionControllerSelector : DefaultHttpControllerSelector 2 { 3 private HttpConfiguration config; 4 private IDictionary<string, HttpControllerDescriptor> mCtrlMapping; 5 public VersionControllerSelector(HttpConfiguration config) : base(config) 6 { 7 this.config = config; 8 } 9 /// <summary> 10 /// 获取所有的controller,并注册 11 /// </summary> 12 /// <returns></returns> 13 public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() 14 { 15 Dictionary<string, HttpControllerDescriptor> dict = new Dictionary<string, HttpControllerDescriptor>(); 16 foreach (var asm in config.Services.GetAssembliesResolver().GetAssemblies()) 17 { 18 //获取继承自ApiController的非抽象类 19 var controllerTypes = asm.GetTypes() 20 .Where(e => !e.IsAbstract && typeof(ApiController).IsAssignableFrom(e)).ToArray(); 21 //获取controller的名字 22 foreach (var ctrlType in controllerTypes) 23 { 24 string ctrlTypeNs = ctrlType.Namespace; 25 var match = Regex.Match(ctrlTypeNs, @"\.v(\d+)"); 26 if (match.Success) 27 { 28 string verNum = match.Groups[1].Value;//把版本号中的数字提取出来 29 string ctrlTypeName = ctrlType.Name;//controller名字 30 var matchController = Regex.Match(ctrlTypeName, @"^(.+)Controller$"); 31 if (!matchController.Success) 32 { 33 continue; 34 } 35 string ctrlName = matchController.Groups[1].Value; 36 string key = ctrlName + "v" + verNum;//个性约定 37 dict[key] = new HttpControllerDescriptor(config, ctrlName, ctrlType); 38 } 39 } 40 mCtrlMapping=dict; 41 } 42 return dict; 43 } 44 45 /// <summary> 46 /// 返回HttpControllerDescriptor的过程 47 /// </summary> 48 /// <param name="request"></param> 49 /// <returns></returns> 50 public override HttpControllerDescriptor SelectController(HttpRequestMessage request) 51 { 52 string controller = (string)request.GetRouteData().Values["controller"]; 53 if (mCtrlMapping == null) { 54 mCtrlMapping = GetControllerMapping(); 55 } 56 57 var matchVer = Regex.Match(request.RequestUri.PathAndQuery, @"/v(\d+)/"); 58 if (!matchVer.Success) 59 { 60 return base.SelectController(request); 61 } 62 string verNum = matchVer.Groups[1].Value; 63 string key = controller + "v" + verNum; 64 if (mCtrlMapping.ContainsKey(key)) 65 { 66 return mCtrlMapping[key]; 67 } 68 else 69 { 70 return base.SelectController(request); 71 } 72 } 73 }
3.在config中注册注册VersionControllerSelector类
config.Services.Replace(typeof(IHttpControllerSelector), new VersionControllerSelector(config));
作者:大胖儿在努力
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。