using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; namespace Pcb.Api.App_Start { public class AreaHttpControllerSelector : DefaultHttpControllerSelector { private readonly HttpConfiguration _configuration; private const string CONTROLLER_FULL_NAME_PREFIX = "Pcb.Api.Controllers"; /// /// Lazy 当前程序集中包含的所有IHttpController反射集合,TKey为小写的Controller /// private readonly Lazy> _apiControllerTypes; private ILookup ApiControllerTypes { get { return this._apiControllerTypes.Value; } } /// /// Initializes a new instance of the AreaHttpControllerSelector class /// /// public AreaHttpControllerSelector(HttpConfiguration configuration) : base(configuration) { this._configuration = configuration; this._apiControllerTypes = new Lazy>(this.GetApiControllerTypes); } /// /// 获取当前程序集中 IHttpController反射集合 /// /// private ILookup GetApiControllerTypes() { IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver(); return this._configuration.Services.GetHttpControllerTypeResolver() .GetControllerTypes(assembliesResolver) .ToLookup(t => t.Name.ToLower().Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length), t => t); } /// /// Selects a System.Web.Http.Controllers.HttpControllerDescriptor for the given System.Net.Http.HttpRequestMessage. /// /// /// public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { HttpControllerDescriptor des = null; string controllerName = this.GetControllerName(request); if (!string.IsNullOrWhiteSpace(controllerName)) { var groups = this.ApiControllerTypes[controllerName.ToLower()]; if (groups != null && groups.Any()) { string endString; var routeDic = request.GetRouteData().Values;//存在controllerName的话必定能取到IHttpRouteData if (routeDic.Count > 1) { StringBuilder tmp = new StringBuilder(); foreach (var key in routeDic.Keys) { tmp.Append('.'); tmp.Append(routeDic[key]); if (key.Equals(DefaultHttpControllerSelector.ControllerSuffix, StringComparison.CurrentCultureIgnoreCase)) {//如果是control,则代表命名空间结束 break; } } tmp.Append(DefaultHttpControllerSelector.ControllerSuffix); endString = tmp.ToString(); } else { endString = string.Format(".{0}{1}", controllerName, DefaultHttpControllerSelector.ControllerSuffix); } //取NameSpace节点数最少的Type //var type = groups.Where(t => t.FullName.EndsWith(endString, StringComparison.CurrentCultureIgnoreCase)) // .OrderBy(t => t.FullName.Count(s => s == '.')).FirstOrDefault();//默认返回命名空间节点数最少的第一项 string controllerFullName = CONTROLLER_FULL_NAME_PREFIX + endString; var type = groups.SingleOrDefault(t => controllerFullName.Equals(t.FullName, StringComparison.CurrentCultureIgnoreCase)); if (type != null) { des = new HttpControllerDescriptor(this._configuration, controllerName, type); } } } if (des == null) { //throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, // string.Format("No route providing a controller name was found to match request URI '{0}'", request.RequestUri))); throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("没有路由能够提供对应的控制器名字, Url:'{0}'", request.RequestUri))); } return des; } public override IDictionary GetControllerMapping() { var value = this.ApiControllerTypes.ToDictionary(n => n.Key, n => new HttpControllerDescriptor(this._configuration, n.Key, n.First())); return this.ApiControllerTypes.ToDictionary(n => n.Key, n => new HttpControllerDescriptor(this._configuration, n.Key, n.First())); } } }