你的位置:首页 > ASP.net教程

[ASP.net教程]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.Dispatcherpublic 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.Dispatcherpublic 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