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             );
View Code

 

  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     }
View Code

 

  3.在config中注册注册VersionControllerSelector类

  config.Services.Replace(typeof(IHttpControllerSelector), new VersionControllerSelector(config));

posted @ 2017-10-18 17:06  大胖儿在努力  阅读(643)  评论(0)    收藏  举报