結合此文章:http://www.cnblogs.com/wuhuacong/p/5828038.html
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;
namespace PEMSoft.Web.AppServer
{
/// <summary>
/// Area路由控制,如URL中含{action}則通過Area查詢控制器,不存在{area}或找不到控制器則按預設規則再找一次
/// 作者:ifu25
/// 日期:2017/07/08
/// 參考:http://www.jianshu.com/p/8242215cd8c0 、 http://www.cnblogs.com/Silicon-Fado/p/3571938.html
/// </summary>
public class AreaHttpControllerSelector : DefaultHttpControllerSelector
{
#region 變數
/// <summary>
/// Area名稱
/// </summary>
private const string _areaRouteVariableName = "area";
private readonly HttpConfiguration _configuration;
private Dictionary<string, Type> _apiControllerTypes;
/// <summary>
/// 所有API控制器集合
/// </summary>
private Dictionary<string, Type> ApiControllerTypes
{
get { return _apiControllerTypes ?? (_apiControllerTypes = GetControllerTypes()); }
}
#endregion
/// <summary>
/// 構造
/// </summary>
public AreaHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
}
/// <summary>
/// 覆寫父類的選擇控制器方法,通過此方法實現根據Area查詢控制器
/// </summary>
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
//選通過Area查詢控制器,找不到則忽略Area再找一次
return GetApiController(request) ?? base.SelectController(request);
}
#region 內部方法
/// <summary>
/// 獲取所有控制器
/// </summary>
private static Dictionary<string, Type> GetControllerTypes()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var types = assemblies.SelectMany(a => a.GetTypes().Where(t => !t.IsAbstract && t.Name.EndsWith(ControllerSuffix) && typeof(IHttpController).IsAssignableFrom(t)))
.ToDictionary(t => t.FullName, t => t);
return types;
}
/// <summary>
/// 為給定的HttpRequestMessage選擇帶Area的控制器,沒有Area則返回null
/// </summary>
private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
{
var controllerName = base.GetControllerName(request);
var areaName = GetAreaName(request);
if (string.IsNullOrEmpty(areaName))
{
return null;
}
var type = GetControllerTypeByArea(areaName, controllerName);
if (type == null)
{
return null;
}
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
/// <summary>
/// 從HttpRequestMessage獲取Area,沒有指定Area則返回null
/// </summary>
private static string GetAreaName(HttpRequestMessage request)
{
var data = request.GetRouteData();
if (!data.Values.ContainsKey(_areaRouteVariableName))
{
return null;
}
return data.Values[_areaRouteVariableName].ToString().ToLower();
}
/// <summary>
/// 獲取指定Area下的控制器
/// </summary>
/// <param name="areaName">Area名稱</param>
/// <param name="controllerName">控制器名稱</param>
private Type GetControllerTypeByArea(string areaName, string controllerName)
{
var areaNameToFind = string.Format(".{0}.", areaName.ToLower());
var controllerNameToFind = string.Format(".{0}{1}", controllerName, ControllerSuffix);
return ApiControllerTypes.Where(t => t.Key.ToLower().Contains(areaNameToFind) && t.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase))
.Select(t => t.Value).FirstOrDefault();
}
#endregion
}
}