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的模 ...
随机推荐
- UVA.10325 The Lottery (组合数学 容斥原理 二进制枚举)
UVA.10325 The Lottery (组合数学 容斥原理) 题意分析 首先给出一个数n,然后给出m个数字(m<=15),在[1-n]之间,依次删除给出m个数字的倍数,求最后在[1-n]之 ...
- [Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法(转)
[Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法http://blog.csdn.net/qiujuer/article/details/ ...
- 丁酉年六月十一ACM模拟赛
似乎该写题解了.今天模拟ACM,10道题(本来还有2道被删了),9道都来自BZOJ,中间我做过2道.那么说,今天Solv.便大大增多了(但还是不如强大的Amphetamine). 题单及一句话题解如下 ...
- Maven问题合集
背景:总结maven使用过程中的相关问题,方便以后查询! 1 问题汇总 今天在导入github上下载的maven项目时候,出现了一堆错误,一时间不知道该如何下手. 根据错误提示,发现是一些依赖的jar ...
- freemark的常用方法
1,截取字符串 有的时候我们在页面中不需要显示那么长的字符串,比如新闻标题,这样用下面的例子就可以自定义显示的长度 < lt. <= lte. > gt. >= gte < ...
- Qt 状态栏设置
版权声明 该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处! 导语 在程序主窗口QMainWindow中,主要包含菜单栏,工具栏,中心部件和状 ...
- linux命令总结之route命令
route命令用于显示和操作IP路由表.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是 为了解决以下问题:该Linu ...
- NO.1 Day 计算机基础
计算机基础 1.编程语言的作用及与操作系统和硬件的关系 编程语言是程序员与计算机之间沟通的媒介. 一套完整的计算机系统分为计算机硬件.操作系统和软件三部分.编程语言开发的结果为软件.软件的运行在操作系 ...
- 二叉树(前序,中序,后序,层序)遍历递归与循环的python实现
二叉树的遍历是在面试使比较常见的项目了.对于二叉树的前中后层序遍历,每种遍历都可以递归和循环两种实现方法,且每种遍历的递归实现都比循环实现要简洁.下面做一个小结. 一.中序遍历 前中后序三种遍历方法对 ...
- Go_18: Golang 中三种读取文件发放性能对比
Golang 中读取文件大概有三种方法,分别为: 1. 通过原生态 io 包中的 read 方法进行读取 2. 通过 io/ioutil 包提供的 read 方法进行读取 3. 通过 bufio 包提 ...