Asp.net WebApi版本控制
2016-04-09 18:28
411 查看
关web api的版本控制网上有很多,如Web
API 版本控制的几种方式 Web
API 版本化的介绍 但是具体的code并不多,或者说可以run的demo 不多。
版本控制如果项目一开始还好做关键是很多项目都在中后期才引入版本控制。如:
如这里的ValuesController先前是没有版本控制的,可能项目运行一段时间后才需要增加版本控制,不得影响已有的使用哦。
版本控制的原理主要就是如何确定controler。新建VersionHttpControllerSelector如下:
同时需要修改WebApiConfig.cs如下:
我的demo中的version可以从url获取也可以从request header中获取。至于实际中把version放在url还是request中还的根据实际情况。 如标准中推荐放到request header中,但是实际放在url中比较一目了然。并且在跨域的时候可能 减少预请求。
再强调一下 这里的版本控制主要是控制controler的版本,也就是SelectController方法。
下载地址 http://download.csdn.net/detail/dz45693/9486586
API 版本控制的几种方式 Web
API 版本化的介绍 但是具体的code并不多,或者说可以run的demo 不多。
版本控制如果项目一开始还好做关键是很多项目都在中后期才引入版本控制。如:
如这里的ValuesController先前是没有版本控制的,可能项目运行一段时间后才需要增加版本控制,不得影响已有的使用哦。
版本控制的原理主要就是如何确定controler。新建VersionHttpControllerSelector如下:
public class VersionHttpControllerSelector : IHttpControllerSelector { private const string VersionKey = "version"; private const string ControllerKey = "controller"; private readonly HttpConfiguration _configuration; private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers; private readonly HashSet<string> _duplicates; public VersionHttpControllerSelector(HttpConfiguration config) { _configuration = config; _duplicates = new HashSet<string>(StringComparer.OrdinalIgnoreCase); _controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDictionary); } private Dictionary<string, HttpControllerDescriptor> InitializeControllerDictionary() { var dictionary = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase); // Create a lookup table where key is "namespace.controller". The value of "namespace" is the last // segment of the full namespace. For example: // MyApplication.Controllers.V1.ProductsController => "V1.Products" IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver(); IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver(); ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver); foreach (Type t in controllerTypes) { var segments = t.Namespace.Split(Type.Delimiter); // For the dictionary key, strip "Controller" from the end of the type name. // This matches the behavior of DefaultHttpControllerSelector. var controllerName = t.Name.Remove(t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length); string version=segments[segments.Length - 1]; var key = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", version, controllerName); if (version == "Controllers") { key = String.Format(CultureInfo.InvariantCulture, "{0}", controllerName); } // Check for duplicate keys. if (dictionary.Keys.Contains(key)) { _duplicates.Add(key); } else { dictionary[key] = new HttpControllerDescriptor(_configuration, t.Name, t); } } // Remove any duplicates from the dictionary, because these create ambiguous matches. // For example, "Foo.V1.ProductsController" and "Bar.V1.ProductsController" both map to "v1.products". foreach (string s in _duplicates) { dictionary.Remove(s); } return dictionary; } // Get a value from the route data, if present. private static T GetRouteVariable<T>(IHttpRouteData routeData, string name) { object result = null; if (routeData.Values.TryGetValue(name, out result)) { return (T)result; } return default(T); } public HttpControllerDescriptor SelectController(HttpRequestMessage request) { IHttpRouteData routeData = request.GetRouteData(); if (routeData == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } // Get the version and controller variables from the route data. string version = GetRouteVariable<string>(routeData, VersionKey); if (string.IsNullOrEmpty(version)) { version = GetVersionFromHTTPHeaderAndAcceptHeader(request); } string controllerName = GetRouteVariable<string>(routeData, ControllerKey); if (controllerName == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } // Find a matching controller. string key = String.Format(CultureInfo.InvariantCulture, "{0}", controllerName); if (!string.IsNullOrEmpty(version)) { key = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", version, controllerName); } HttpControllerDescriptor controllerDescriptor; if (_controllers.Value.TryGetValue(key, out controllerDescriptor)) { return controllerDescriptor; } else if (_duplicates.Contains(key)) { throw new HttpResponseException( request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Multiple controllers were found that match this request.")); } else { throw new HttpResponseException(HttpStatusCode.NotFound); } } public IDictionary<string, HttpControllerDescriptor> GetControllerMapping() { return _controllers.Value; } private string GetVersionFromHTTPHeaderAndAcceptHeader(HttpRequestMessage request) { if (request.Headers.Contains(VersionKey)) { var versionHeader = request.Headers.GetValues(VersionKey).FirstOrDefault(); if (versionHeader != null) { return versionHeader; } } var acceptHeader = request.Headers.Accept; foreach (var mime in acceptHeader) { if (mime.MediaType == "application/json" || mime.MediaType == "text/html") { var version = mime.Parameters .Where(v => v.Name.Equals(VersionKey, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (version != null) { return version.Value; } return string.Empty; } } return string.Empty; } }
同时需要修改WebApiConfig.cs如下:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultVersion", routeTemplate: "api/{version}/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Services.Replace(typeof(IHttpControllerSelector), new VersionHttpControllerSelector((config))); } }
namespace WebApi.Controllers { public class ValuesController : ApiController { public HttpResponseMessage Get() { return new HttpResponseMessage() { Content = new StringContent("This is a value response.") }; } } } namespace WebApi.Controllers.V1 { public class ValuesController : ApiController { public HttpResponseMessage Get() { return new HttpResponseMessage() { Content = new StringContent("This is a V1 response.") }; } } } namespace WebApi.Controllers.V2 { public class ValuesController : ApiController { public HttpResponseMessage Get() { return new HttpResponseMessage() { Content = new StringContent("This is a V2 response.") }; } } }
我的demo中的version可以从url获取也可以从request header中获取。至于实际中把version放在url还是request中还的根据实际情况。 如标准中推荐放到request header中,但是实际放在url中比较一目了然。并且在跨域的时候可能 减少预请求。
再强调一下 这里的版本控制主要是控制controler的版本,也就是SelectController方法。
下载地址 http://download.csdn.net/detail/dz45693/9486586
相关文章推荐
- Asp.net WebApi版本控制
- 8种提升ASP.NET Web API性能的方法
- Asp.net WebAPi Restful 的实现和跨域
- Asp.net WebAPi Restful 的实现和跨域
- 记一次ASP.NET MVC性能优化(实际项目中)
- ASP.NET之通过JS向服务端(后台)发出请求(__doPostBack is undefined)
- asp.net 预编译和动态编译
- ASP.NET MVC5 高级编程 第3章 视图
- ASP.NET MVC5 高级编程 第2章 控制器
- ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法
- Asp.net MVC中关于@Html标签的使用
- asp.net中信息存储---session、cache、viewstate等的区别
- ASP.NET页面跳转的三种方法比较
- asp.net获取客户端浏览器及主机信息
- asp.net 柱形图
- asp.net 生成图形验证码(字母和数字混合)
- asp.net 网页抓取内容
- ASP.NET上传下载
- 微软ASP.NET网站部署指南(4):配置项目属性
- asp.net mvc 返回音频,可支持快进