zoukankan      html  css  js  c++  java
  • ASP.NET Web API中实现版本的几种方式

    在ASP.NET Web API中,当我们的API发生改变,就涉及到版本问题了。如何实现API的版本呢?

    1、通过路由设置版本

    最简单的一种方式是通过路由设置,不同的路由,不同的版本,不同的controller。

    config.Routes.MapHttpRoute(
        name: "Food",
        routeTemplate: "api/v1/nutrition/foods/{foodid}",
        defaults:...
    )
    
    config.Routes.MapHttpRoute(
        name: "Foodv2",
        routeTemplate: "api/v2/nutrition/foods/{foodid}",
        defaults:...
    )

    2、通过HttpControllerSelector

    通过更改HttpControllerSelector也可以实现。

    首先写一个继承 DefaultHttpControllerSelector的类。

    using System.Web.http.Dispatcher
    
    public class CountingKsControllerSelector : DefaultHttpControllerSelector
    {
        private HttpConfiguraion _config;
        
        public CountgKsControllerSelector(HttpConfiguraiton cofig) : base(config)
        {
            _config = config;
        }
        
        //设计就是返回HttpControllerDesriptor的过程
        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"];
            
            HttpControllerDescriptor descriptor;
            
            if(controllers.TryGetValue(controllerName, out descriptor))
            {
                var version = "2";
                
                //从QueryString中获取版本 
                var newName = string.Concat(controllerName, "V", version);
                
                HttpControllerDescriptor versionedDescriptor;
                
                if(controllers.TryGetValue(newName, out versionedDescriptor))
                {
                    return versionedDescriptor;
                }
                
                return descriptor;
            }
            
            return null;
            
        }
    }

    在WebApiConfig.cs注册自定义的ControllerSelector

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

    以上是大致的实现思路。具体来说可以通过如下几种方式实现。

    ■ 通过Query String实现版本

    客户端大致这样请求:

    http://localhost:8901/api/nutrition/foods/4492/measures/7269?v=2

    using System.Web.http.Dispatcher
    
    public class CountingKsControllerSelector : DefaultHttpControllerSelector
    {
        private HttpConfiguraion _config;
        
        public CountgKsControllerSelector(HttpConfiguraiton cofig) : base(config)
        {
            _config = config;
        }
        
        //设计就是返回HttpControllerDesriptor的过程
        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"];
            
            HttpControllerDescriptor descriptor;
            
            if(controllers.TryGetValue(controllerName, out descriptor))
            {
                //var version = "2";
                
                //从QueryString中获取版本 
                var version = GetVersionFromQueryString(request);
                
                var newName = string.Concat(controllerName, "V", version);
                
                HttpControllerDescriptor versionedDescriptor;
                
                if(controllers.TryGetValue(newName, out versionedDescriptor))
                {
                    return versionedDescriptor;
                }
                
                return descriptor;
            }
            
            return null;
            
        }
        
        //从QueryString中获取版本 
        private string GetVersionFromQueryString(HttpRequestMessage request)
        {
            var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
            var version = query["v"];
            if(version != null)
            {
                return version;
            }
            
            return "1";
        }
    }

    ■ 通过Header实现版本

    客户端大致这样请求:

    User-Agent:Fiddler
    Host:locahohost:8901
    X-CountingKs-Version:2

    private string GetVersionFromHeader(HttpRequestMessage request)
    {
        const string HEADER_NAME = "X-CountingKs-Version";
        
        if(request.Headers.Contains(HEADER_NAME))
        {
            var header = request.Headers.GetValues(HEADER_NAME).FirstOrDefault();
            
            if(header != null)
            {
                return header;
            }
        }
        return "1";
    }

    ■ 通过Accept-Header实现版本

    客户端大致这样请求:

    User-Agent:Fiddler
    Host:locahohost:8901
    Accept: application/json;version=2

    private string GetVersionFromAcceptHeaderVersion(HttpRequestMessage request)
    {
        var accept = request.Headers.Accept;
        
        foreach(var mime in accept)
        {
            if(mime.MediaType == "applicaiton/json")
            {
                var value = mime.Parameters
                    .Where(v => v.Name.Equals("version",StringComparison.OrdinalIngoreCase))
                    .FirstOrDefault();
                
                return value.Value;
            }
        }
        
        return "1";
        
    }

    ■ 通过MediaType实现版本

    在WebApiConfig.cs中

    var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
    jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    
    CreateMediaTypes(jsonFormatter);
    
    
    private static void CreateMediaTypes(JsonMediaTypeFormatter jsonFormatter)
    {
        var mediaTypes = new string[]
        {
            "application/vnd.counting,s.food.v1+json",
            "application/vnd.countingks.measure.v1+json",
            "application/vnd.countgks.measure.v2+json",
            "applicatikon/vnd.countingks.diary.v1+json",
            "application/vnd.countingks.diaryEntry.v1+json"
        };
        
        foreach(var mediaType in mediaTypes)
        {
            jsonFormatter.SupportedMeidaTypes.Add(new MediaTypeHeaderValue(mediaType));
        }
    }

    在客户端大致这样请求:

    User-Agent:Fiddler
    Host:localhost:8901
    Accept:application/vnd.countingks.food.v1+json

    private string GetVersonFromMediaType(HttpRequestMessage request)
    {
        var accept = request.Headers.Accept;
        var ex = new Regex(@"application/vnd.countingks.([a-z]+).v([0-9]+)+json". RegexOptions.IgnoreCase);
        
        foreach(var mime in accept)
        {
            var match = ex.Match(mime.MediaType);
            if(match != null)
            {
                return match.Groups[2].Value;
            }
        }
        return "1";
    }


    ■ 使用SDammann.WebApi.Versioning

    https://github.com/Sebazzz/SDammann.WebApi.Versioning

  • 相关阅读:
    HUD——T 3836 Equivalent Sets
    HDU——T 2594 Simpsons’ Hidden Talents
    vertical-align和line-height的深入应用
    November 7th 2016 Week 46th Monday
    November 6th 2016 Week 46th Sunday
    November 5th Week 45th Saturday 2016
    November 4th Week 45th Friday 2016
    【2017-01-08】QTimer与QThread的调度时间精度
    November 3rd Week 45th Thursday 2016
    November 2nd Week 45th Wednesday 2016
  • 原文地址:https://www.cnblogs.com/darrenji/p/5138954.html
Copyright © 2011-2022 走看看