WebApi支持命名空间重名问题
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;
namespace ZQNB.Common.Web.Api
{
//针对WebApi的扩展
//目的是为了让WebApi支持命名空间的筛选
//程序启动时,替换IHttpControllerSelector选择器
//GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));
public static class HttpRouteCollectionEx
{
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, string[] namespaces)
{
return routes.MapHttpRoute(name, routeTemplate, defaults, null, null, namespaces);
}
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler, string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
var routeValue = new HttpRouteValueDictionary(new { Namespace = namespaces });//设置路由值
var route = routes.CreateRoute(routeTemplate, new HttpRouteValueDictionary(defaults), new HttpRouteValueDictionary(constraints), routeValue, handler);
routes.Add(name, route);
return route;
}
}
public class NamespaceHttpControllerSelector : DefaultHttpControllerSelector
{
private const string NamespaceRouteVariableName = "Namespace";
private readonly HttpConfiguration _configuration;
private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache;
public NamespaceHttpControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
_configuration = configuration;
_apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
}
private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
{
IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
var types = this._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t);
return new ConcurrentDictionary<string, Type>(types);
}
public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
{
object namespaceName;
var apiControllerKeys = Enumerable.Empty<string>();
string[] namespaces = null;
var data = request.GetRouteData();
IEnumerable<string> allApiControllers = _apiControllerCache.Value.ToDictionary(t => t.Key,
t => t.Value, StringComparer.CurrentCultureIgnoreCase).Keys.ToList();
namespaces = (string[]) this.GetRouteValue(NamespaceRouteVariableName, data);
if (namespaces != null && namespaces.Any())
{
var area = (string) this.GetRouteValue("area", data);
if (!string.IsNullOrEmpty(area))
{
for (int i = 0; i < namespaces.Length; i++)
{
if (namespaces[i].Contains("{area}"))
{
namespaces[i] = namespaces[i].Replace("{area}", area);
}
}
}
return from n in namespaces
join k in allApiControllers on
string.Format("{0}.{1}{2}", n, controllerName, DefaultHttpControllerSelector.ControllerSuffix)
.ToLower() equals k.ToLower()
select k;
}
//get the defined namespace
return allApiControllers.Where(
k =>
k.EndsWith(
string.Format(".{0}{1}", controllerName, DefaultHttpControllerSelector.ControllerSuffix),
StringComparison.CurrentCultureIgnoreCase));
}
private object GetRouteValue(string key, IHttpRouteData httpRouteData)
{
object value;
if (httpRouteData.Route.DataTokens != null &&
httpRouteData.Route.DataTokens.TryGetValue(key, out value))
{
if (value != null)
{
return value;
}
}
if (httpRouteData.Values != null && httpRouteData.Values.TryGetValue(key, out value))
{
if (value != null)
{
return value;
}
}
return null;
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
Type type;
if (request == null)
{
throw new ArgumentNullException("request");
}
string controllerName = this.GetControllerName(request);
if (string.IsNullOrEmpty(controllerName))
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
}
IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
var enumerable = fullNames as string[] ?? fullNames.ToArray();
if (!enumerable.Any())
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
}
//如果能匹配上多个,排除优先选择不在限制内的命名空间
if (this._apiControllerCache.Value.TryGetValue(enumerable.First(), out type))
{
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
}
}
}
最后Global
//设置我们自己的 ControllerFactory
ControllerBuilder.Current.SetControllerFactory(new NbDefaultControllerFactory(CoreServiceProvider.Current.GetAllInstances<IControllerProvider>()));
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));
WebApi支持命名空间重名问题的更多相关文章
- MVC5为WebAPI添加命名空间的支持
前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...
- asp.net MVC5为WebAPI添加命名空间的支持
前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...
- MVC5为WebAPI添加命名空间的支持1
前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...
- partial修饰符,可以让同类命名空间下出现重名
public partial class Person { } public partial class Person { } partial修饰符,可以让同类命名空间下出现重名,两个类其实是一个类, ...
- 在IE中,JS方法名和input的name重名时,调用该方法无效
在IE中,JS方法名和input的name重名时,调用该方法无效.提示:网页错误详细信息 用户代理: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1 ...
- 规避Javascript多人开发函数和变量重名问题
函数和变量重名始终是一个令人头痛的问题,先讲变量吧,相信了解JS的朋友都知道,在JS中 是没有块级作用域的只有函数作用域,也就是说那些以大括号为界定符的代码块是管不住其中定义 的变量的作用域的,举例: ...
- JS重名解决方案
一个页面如果引用多个JS,或者像ASP.NET MVC,一个视图包含多个子视图,每个子视图有自己的JS,那么变量.函数的重名冲突机会将会大增. 如何解决? 这里有一个方案: 1.用类来封装子页的JS代 ...
- 4.4 ROS节点名称重名
4.4 ROS节点名称重名 场景:ROS 中创建的节点是有名称的,C++初始化节点时通过API:ros::init(argc,argv,"xxxx");来定义节点名称,在Pytho ...
- js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败
今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...
随机推荐
- 用nodejs搭建一个简单的服务器
使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...
- python设计模式1:创建型模式
1.原型模式 如果想根据现有的对象复制出新的对象并进行修改,可以考虑“原型模式”,而无需知道任何创建细节.(有点像写轮眼...你不需要知道它) import copy class Point: __s ...
- oracle 事务总结
用了这么长时间的oracle,该总结一下所得了 1,事务 事务用于保证数据的一致性, 它由一组相关的 dml语句组成, 该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败,比 ...
- MySQL Index详解
FROM:http://blog.csdn.net/tianmo2010/article/details/7930482 ①MySQL Index 一.SHOW INDEX会返回以下字段 1.Tabl ...
- ASP.NET点击按钮弹出确认对话框方法
开发asp.net网页应用程序的时候,有些页面的按钮需要增加一个确认对话框,比如: 实现这个功能比较简单,代码这样写: Button.Attributes["onclick"] = ...
- ListView实现原理
转载:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android所有常用的原生控件当中,用法最复杂的应该就是ListView了 ...
- FastReport 隐藏matrix的列如何实现
fastReport在处理 行列都是浮动的时候非常好用. 但是也有一些不太直观的东西.比如说要设置生成结果的某行某列. 修改字体颜色背景色,隐藏,设置行高,设置列宽等等. 可以在 matrix的aft ...
- Paxos变种和优化
分布式系统理论进阶 - Paxos变种和优化 引言 <分布式系统理论进阶 - Paxos>中我们了解了Basic Paxos.Multi Paxos的基本原理,但如果想把Paxos应用于工 ...
- Centos 7 安装jdk 配置环境变量
在Centos7 终端中,我们输入java -version可以看到java的版本,但是输入javac却没有反应 原因是系统中预装的是openjdk jre不是真正的jdk,所以还得自己装好,然后配置 ...
- Spring Security笔记:自定义登录页
以下内容参考了 http://www.mkyong.com/spring-security/spring-security-form-login-example/ 接上回,在前面的Hello Worl ...