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的模 ...
随机推荐
- BZOJ 1013 | 一份写了一堆注释的高斯消元题解
题意 给出\(n\)维直角坐标系中\(n + 1\)个点的坐标,它们都在一个\(n\)维球面上,求球心坐标. 题解 设球面上某两个点坐标为\((a_1, a_2, ... a_n)\)和\((b_1, ...
- 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告
P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...
- 搭建ELK收集Nginx日志
众所周知,ELK是日志收集套装,这里就不多做介绍了. 画了一个粗略的架构图,如下: 这里实际用了三个节点,系统版本为CentOS6.6,ES版本为2.3.5,logstash版本为2.4.0,kiba ...
- WEB入门.九 导航菜单
学习内容 水平导航菜单 垂直导航菜单 下拉式导航菜单 能力目标 制作tab标签导航菜单 制作带箭头的导航菜单 制作带信息提示的导航菜单 制作垂直下拉导航菜单 制作水平下拉导航菜单 本章简介 上一章节中 ...
- SSM的整合
框架的整合: 1. 依赖整合 aop的包: aspectweaver spring-aop spring核心: spring-context spring-web spring-webmvc spri ...
- 解题:USACO07FEB The Cow Lexicon
题面 第一次做Trie上dp,感谢 @i207M 的资瓷 对子串们建立一棵Trie,设$dp[i][j]$表示到母串第$i$位为止在$Trie$上的$j$号节点时的最小修改数量,然后就可以枚举母串各位 ...
- 【bzoj4337】【Bjoi2015】树的同构
题解 无标号树的HASH: 找到树的重心,以重心为根求出括号序列: 由于树的重心最多只有两个,取字典序的最小括号序列HASH即可 树的括号序列$s_{u}="(s_{v_{1}},s_{v_ ...
- springboot中如何添加第三方的jar包或者说如何配置本地jar
首先推荐博客: spring-boot-maven-plugin 安装本地jar 包 http://www.cnblogs.com/acm-bingzi/p/mavenSpringBootPlugin ...
- python学习(22) 访问数据库
原文链接:http://www.limerence2017.com/2018/01/11/python22/ 本文介绍python如何使用数据库方面的知识. SQLite SQLite是一种嵌入式数据 ...
- css基础--常用css属性01
1 背景相关 背景颜色 background-color = 颜色名称/rgb值/十六进制值 背景图片 background-image = url('') 背景图片平铺方式 backgro ...