AreaHttpControllerSelector 对 Web Api 实现 Area 路由控制

结合此文章: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
    }
}
posted @ 2018-10-27 09:48  微酷  阅读(958)  评论(0编辑  收藏  举报