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支持命名空间重名问题的更多相关文章

  1. MVC5为WebAPI添加命名空间的支持

    前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...

  2. asp.net MVC5为WebAPI添加命名空间的支持

    前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...

  3. MVC5为WebAPI添加命名空间的支持1

    前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...

  4. partial修饰符,可以让同类命名空间下出现重名

    public partial class Person { } public partial class Person { } partial修饰符,可以让同类命名空间下出现重名,两个类其实是一个类, ...

  5. 在IE中,JS方法名和input的name重名时,调用该方法无效

    在IE中,JS方法名和input的name重名时,调用该方法无效.提示:网页错误详细信息 用户代理: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1 ...

  6. 规避Javascript多人开发函数和变量重名问题

    函数和变量重名始终是一个令人头痛的问题,先讲变量吧,相信了解JS的朋友都知道,在JS中 是没有块级作用域的只有函数作用域,也就是说那些以大括号为界定符的代码块是管不住其中定义 的变量的作用域的,举例: ...

  7. JS重名解决方案

    一个页面如果引用多个JS,或者像ASP.NET MVC,一个视图包含多个子视图,每个子视图有自己的JS,那么变量.函数的重名冲突机会将会大增. 如何解决? 这里有一个方案: 1.用类来封装子页的JS代 ...

  8. 4.4 ROS节点名称重名

    4.4 ROS节点名称重名 场景:ROS 中创建的节点是有名称的,C++初始化节点时通过API:ros::init(argc,argv,"xxxx");来定义节点名称,在Pytho ...

  9. js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败

    今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...

随机推荐

  1. Mysql备份系列(2)--mysqldump备份(全量+增量)方案操作记录

    在日常运维工作中,对mysql数据库的备份是万分重要的,以防在数据库表丢失或损坏情况出现,可以及时恢复数据. 线上数据库备份场景:每周日执行一次全量备份,然后每天下午1点执行MySQLdump增量备份 ...

  2. 启动Eclipse后卡在 android sdk content loader 的解决办法

    Make sure that eclipse is not active. If it is active kill eclipse from the processes tab of the tas ...

  3. JS给文本框赋值后,在页面后台取不到文本框值的解决方法

    转自:http://www.cnblogs.com/qiaohd/archive/2012/03/23/2413660.html (ReadOnly.disabled 都有可能造成取值取不到) 开发一 ...

  4. Java 集合系列01之 总体框架

      Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等.Java集合工具包位置是java.util.*Java集合主要可以划分为4个部分:List列表.Set ...

  5. SQL Server 2005、2008 的 datetime 值范围(转)

    SQL Server 2005.2008 的 datetime 最小值是:1753-01-01 00:00:00 最大值是:9999-12-31 23:59:59.997 这与 .NET 中的 Dat ...

  6. POJ 3714 Raid

    Description After successive failures in the battles against the Union, the Empire retreated to its ...

  7. 2015/11/9用Python写游戏,pygame入门(8):按钮和游戏结束

    昨天没有更新内容,今天相对多写一些. 因为我们已经基本完成游戏框架,但是游戏结束后,并不知道怎样比较好开始.我本来本着懒的原则,想结束后显示一个黑屏,然后你重新点一下鼠标就重新开始.但是那样实在太不像 ...

  8. C#操作Excel时的格式设定(转)

    Excel报表打印的格式设定 1.     表头的设置 Excel._Worksheet myWorksheet; myWorksheet.PageSetup.Orientation = Excel. ...

  9. RabbitMQ官方中文入门教程(PHP版) 第二部分:工作队列(Work queues)

    工作队列 在第一篇教程中,我们已经写了一个从已知队列中发送和获取消息的程序.在这篇教程中,我们将创建一个工作队列(Work Queue),它会发送一些耗时的任务给多个工作者(Works ). 工作队列 ...

  10. Android 全屏显示的方法(不包含状态栏)

    我们都知道在Android中某些功能的实现往往有两种方法:一种是在xml文件中设置相应属性,另一种是用代码实现.同样Android实现全屏显示也可以通过这两种方法实现: 1.在AndroidManif ...