4.C#WebAPI多版本管理介紹及實現方案詳解

1.什麼是 API 的多版本?ajax

說白了就是多版本共存的問題。爲方便你們理解我就舉個例子吧,你們想必都用過Jquery吧,它的1.*版本作到了對低版本IE的支持;2.*版本還保留着ajax,可是再也不支持老舊瀏覽器;3.*版本連ajax都不留了;可是用戶不會升級、用戶拒絕升級等緣由,形成這些舊版本也須要運行,可是新版卻已經修改了規範與舊版舊版衝突了。形成這些舊版本也須要運行使用。再例如咱們手機有Android4.0、5.0、6.0、7.0、8.0或IOS8.0、9.0、十、11同時存在於市場也是相似的。api

2.出現多版本問題咱們一般的作法瀏覽器

舊版接口作成一個分支,除了進行 bug 修改外,舊版本接口再也不作改動;新接口代碼繼續演化升級。在客戶端請求的時候帶着要請求的接口版本號,在服務器端選擇合適的版本代碼進行處理。服務器

3.技術處理方案app

(1)(最推薦)不一樣版本用不一樣的域名:v1.api.jiyuwu.com、v2.api.jiyuwu.com、v3……。ide

(2) 在url、報文頭等中帶不一樣的版本信息,用 Nginx 等作反向代理服務器,而後將 http://api.jiyuwu.com/api/V1/Login/1和http://api.jiyuwu.com/api/V2/Login/1轉到不一樣的服務器處理。url

(3) 多 個 版 本 的 Controller 共 處 在 一 個 項 目 中 , 然 後 使 用 [RoutePrefix] 或 者 IHttpControllerSelector 根據報文頭、路徑等選擇不一樣的 Controller 執行。下面主要講這兩種方法。spa

4.針對3.(3)的兩種方案的案例3d

 (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)配置完畢請求結果如圖:

相關文章
相關標籤/搜索