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()));
}
}
}