Owin WebApi版本控制
- public class WebApiControllerSelector : IHttpControllerSelector
- {
- private const string NamespaceKey = "version";
- private const string ControllerKey = "controller";
- private readonly HttpConfiguration _configuration;
- private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
- private readonly HashSet<string> _duplicates;
- public WebApiControllerSelector(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);
- var key = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", segments[segments.Length - ], controllerName.ToLower());
- // 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;
- }
- // 取路由相应值
- 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);
- }
- //从Route中读取命名空间名称和控制器名称
- string controllerName = GetRouteVariable<string>(routeData, ControllerKey).ToLower();
- if (controllerName == null)
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- HttpControllerDescriptor controllerDescriptor;
- //获取版本号
- var version = GetVersionFromAcceptHeaderVersion(request);
- var versionedControllerName = string.Concat(controllerName, version).ToLower();
- string versionkey = versionedControllerName;
- //寻找匹配项
- HttpControllerDescriptor versionedControllerDescriptor;
- //如果命名空间名称为空,调用BaseRoute,反之采用DefaultApi
- string namespaceName = GetRouteVariable<string>(routeData, NamespaceKey);
- string key = controllerName;
- if (namespaceName != null)
- {
- key = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", namespaceName, controllerName);
- versionkey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", namespaceName, versionedControllerName);
- if (_controllers.Value.TryGetValue(key, out controllerDescriptor))
- {
- if (_controllers.Value.TryGetValue(versionkey, out versionedControllerDescriptor))
- {
- return versionedControllerDescriptor;
- }
- return controllerDescriptor;
- }
- else if (_duplicates.Contains(key))
- {
- throw new HttpResponseException(
- request.CreateErrorResponse(HttpStatusCode.InternalServerError,
- "该请求有多个控制器匹配,请检查路由配置"));
- }
- else
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- }
- else
- {
- var basecontroller = _controllers.Value.Where(p => p.Key.ToLower().EndsWith(key));
- if (basecontroller.Any())
- {
- if (basecontroller.Count() > )
- {
- throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.InternalServerError, "该请求有多个控制器匹配,请检查路由配置"));
- }
- controllerDescriptor = basecontroller.FirstOrDefault().Value;
- var baseVersioncontroller = _controllers.Value.Where(p => p.Key.ToLower().EndsWith(versionkey));
- if (baseVersioncontroller.Any())
- {
- return baseVersioncontroller.FirstOrDefault().Value;
- }
- return controllerDescriptor;
- }
- else
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- }
- }
- public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
- {
- return _controllers.Value;
- }
- /// <summary>
- /// 添加版本控制
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- private string GetVersionFromAcceptHeaderVersion(HttpRequestMessage request)
- {
- var acceptHeader = request.Headers.Accept;
- if (acceptHeader.Any())
- {
- var format = acceptHeader.First();
- format.MediaType = JsonMediaTypeFormatter.DefaultMediaType.MediaType;
- }
- var heads = request.Headers;
- if (heads.Contains("Version"))
- {
- return heads.GetValues("Version").FirstOrDefault();
- }
- return "";
- }
- }
路由:
- // Configure Web API for self-host.
- Config.Routes.MapHttpRoute(
- name: "DefaultApi",
- routeTemplate: "api/oauth2/{version}/{controller}/{action}",
- defaults: new { controller = RouteParameter.Optional, action = RouteParameter.Optional }
- );
- Config.Services.Replace(typeof(IHttpControllerSelector), new WebApiControllerSelector(Config));
Owin WebApi版本控制的更多相关文章
- ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus
ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus 本文承接我的上一篇博文: ASP.NET 5 Linux部署,那篇文章主要是针对最新的ASP. ...
- (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】
适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- ASP.NET Core WebApi版本控制
前言: 在日常项目开发中,随着项目需求不断的累加.不断的迭代:项目服务接口需要向下兼容历史版本:前些时候就因为Api接口为做版本管理导致接口对低版本兼容处理不友好. 最近就像了解下如何实现WebApi ...
- 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务
前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...
- 电商系统架构总结4(webapi 版本控制)
为了 顺利迭代升级,web api 在维护过程是不断升级的,但用户是不能强迫他们每次都跟随你去升级,这样会让用户不胜其烦.为了保证不同版本的客户端能同时兼容,在web api接口上加入版本控制就很有必 ...
- Asp.net WebApi版本控制
有关web api的版本控制网上有很多,如Web API 版本控制的几种方式 Web API 版本化的介绍 但是具体的code并不多,或者说可以run的demo 不多. 版本控制如果项目一开始还好做关 ...
- Owin WebAPI上传文件
Owin是微软出了几年的东东了,一直没时间学习.大概了解了下,是一个脱离IIS环境,快速搭建WebAPI服务的东西. 刚好想尝试下尽量脱离IIS创建简单快捷配置的项目,就是用了Nginx+Owin的模 ...
随机推荐
- Java考试题之六
QUESTION 134 Given:11. class Snoochy {12. Boochy booch;13. public Snoochy() { booch = new Boochy(thi ...
- Android Studio aidl文件路径自定义问题
1.aidl旧文件夹中添加的内容无法编译 sourceSets中主要是把把src/main/aidl文件也作为java.srcDirs, resources.srcDirs,这样当编译程序时,AIDL ...
- Map / HashMap 获取Key值的方法
方法1:keySet()HashMap hashmp = ne HashMap();hashmp.put("aa", "111");Set set = hash ...
- 【纪中集训2019.3.23】Deadline
题意 描述 一个二分图\((A,B)\),每个点额外有一个颜色0或者1: 匹配时,只能相同颜色的点匹配: 给出\(A\)中的颜色,问如何分配\(B\)种的颜色使得\((A,B)\)的最大匹配最小: 范 ...
- codeforces contest 1111
A. Superhero Transformation 题意: 元音和元音,辅音和辅音字母之间可以互相转换,问两个字符串是否想同: 题解:直接判断即可: #include<bits/stdc++ ...
- C#线程篇---你所不知道的线程池(4)
线程的创建和销毁都要耗费大量的时间,有什么更好的办法?用线程池! 太多的线程浪费内存资源,有什么更好的办法?用线程池! 太多线程有损性能,有什么更好的办法?用线程池!(⊙_⊙)? 线程池是什么?继前三 ...
- HDU 6040 stl
Hints of sd0061 Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- 四、java面向对象编程_2
目录 六.对象的创建和使用 七.this关键字 八.static关键字 九.package和import语句 十.类的继承 十一.访问控制 十二.方法的重写 十三.super关键字 十四.继承中的构造 ...
- vue写template的4种形式
1.template标签(非单文件组件) <template id="t1"> <h2>66666666</h2> </template& ...
- P2831 愤怒的小鸟
P2831 愤怒的小鸟 从 \((0, 0)\) 发射一只鸟, 轨迹满足抛物线, 问最少几只鸟可以打完 \(n <= 18\) 只猪 错误日志: 处理抛物线数组没有初始化 Solution 数据 ...