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方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...
随机推荐
- Android webview通过http get下载文件下载两次的问题及解决方法
一.现象 一般通过Android webview进行下载文件的方法是 1.重写DownloadListener的onDownloadStart方法,在onDownloadStart方法中弹出对话框提示 ...
- ONS C++ Windows SDK 调试方法及注意事项
此文将展示ONS C++ Windows SDK 整个调试过程,笔者直接使用sdk包中的example消息发送示例代码,开发环境为win7, 64位,Visual Studio Professiona ...
- NET Core HTTP 管道
ASP.NET Core HTTP 管道中的那些事儿 前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Cor ...
- ORACLE 定时执行存储过程
推荐用dbms_scheduler方式更好 (2012-11-19注) /* 查询: select job,broken,what,interval,t.* from user_jobs t; job ...
- 单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)
首先这两种方式都是延迟初始化机制,就是当要用到的时候再去初始化. 但是Effective Java书中说过:除非绝对必要,否则就不要这么做. 1. DCL (double checked lockin ...
- C# StopWatch的使用
在做项目的时候,需要输出数据库操作的耗时,自己写了个方法.老大看到后,奇怪我为什么不用现成的.才知道有StopWatch这个类. 属性 名称 说明 Elapsed 获取当前实例测量得出的总 ...
- Unity 5.3.1 No Android/IOS module loaded
unity我一直在用5.0以下的版本 昨天升级到了最新版本5.3.1 发现无法打android包,ios也不行 提示“No Android/IOS module loaded” 下面有个Module ...
- linux 内存清理/释放命令
1.清理前内存使用情况 free -m 2.开始清理 echo 1 > /proc/sys/vm/drop_caches 3.清理后内存使用情况 free -m 4.完成! 查看内存条数命令: ...
- linux svn搭建
1 安装: yum install subversion 2 查看svn安装信息: rpm -ql subversion 3 创建svn根目录: svnserve -d -r /svn 4 进入/sv ...
- PotPlayer为播放而生的专业播放器
韩国,比较牛逼的视频播放器.专注与本地视频播放,值得拥有.... 免费下载:http://yunpan.cn/cmZ5ELC6DTI8Y 访问密码 4bf1