一.让Web API路由配置也支持命名空间参数
/// <summary>
    /// controller
    /// 选择器
    /// </summary>
    public class ApiControllerSelerctor : IHttpControllerSelector
    {
        /// <summary>
        /// 版本信息
        /// </summary>
        private const string Version = "ERPVersion";
        private readonly HttpConfiguration _configuration;
        /// <summary>
        /// 延迟加载
        /// </summary>
        private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
        private readonly HashSet<string> _duplicates;

public ApiControllerSelerctor(HttpConfiguration config)
        {
            _configuration = config;
            _duplicates = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            _controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeController);
        }
        /// <summary>
        /// 通过返回基于命名空间的控制器描述符来实现查找
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, HttpControllerDescriptor> InitializeController()
        {
            var dictionary = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
            IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
            IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
            ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
            if (controllerTypes != null)
            {
                foreach (Type t in controllerTypes)
                {
                    var segments = t.Namespace.Split(Type.Delimiter);
                    var controllerName = t.Name.Remove(t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
                    string version = segments[segments.Length - 1];
                    var key = version.Equals("Controllers") ? string.Format(CultureInfo.InvariantCulture, "{0}", controllerName) : string.Format(CultureInfo.InvariantCulture, "{0}.{1}", version, controllerName);
                    if (dictionary.Keys.Contains(key))
                    {
                        _duplicates.Add(key);
                    }
                    else
                    {
                        dictionary[key] = new HttpControllerDescriptor(_configuration, t.Name, t);
                    }
                }
            }
            if (_duplicates != null)
            {
                foreach (string s in _duplicates)
                {
                    dictionary.Remove(s);
                }
            }
            return dictionary;
        }

/// <summary>
        /// 从路由数据,获取一个值
        /// 默认路由版本高于Controller
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="routeData"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private static T GetRouteVariable<T>(IHttpRouteData routeData, string name)
        {
            object result = null;
            if (routeData.Values.TryGetValue(name, out result))
            {
                return (T)result;
            }
            return default(T);
        }

/// <summary>
        /// 对应于自定义控制选择器的命名空间,
        /// 将从HTTP请求消息中获取命名空间和控制器
        /// 然后在字典中查找匹配的控制器
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            IHttpRouteData routeData = request.GetRouteData();
            if (routeData == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            //获取版本号
            string version = GetRouteVariable<string>(routeData, Version);
            if (string.IsNullOrEmpty(version))
            {
                version = GetRequestVersion(request);
            }
            //从Route中读取命名空间名称和控制器名称
            string controllerName = GetRouteVariable<string>(routeData, "controller");
            if (controllerName == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            // 找到一个匹配的控制器
            string controller = string.IsNullOrEmpty(version) ? string.Format(CultureInfo.InvariantCulture, "{0}", controllerName) : string.Format(CultureInfo.InvariantCulture, "{0}.{1}", version, controllerName);

HttpControllerDescriptor controllerDescriptor;
            if (_controllers.Value.TryGetValue(controller, out controllerDescriptor))
            {
                return controllerDescriptor;
            }
            else if (_duplicates.Contains(controller))
            {
                throw new HttpResponseException(
                    request.CreateErrorResponse(HttpStatusCode.InternalServerError,"请检查路由配置"));
            }
            else
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
        {
            return _controllers.Value;
        }
        /// <summary>
        /// 获取请求版本信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private string GetRequestVersion(HttpRequestMessage request)
        {
            if (request.Headers.Contains(Version))
            {
                var versionHeader = request.Headers.GetValues(Version).FirstOrDefault();
                if (versionHeader != null)
                {
                    return versionHeader;
                }
            }
            return string.Empty;
        }
    }

然后在WebApiConfig类的Register中替换服务即可实现

WebApi实现IHttpControllerSelector问题的更多相关文章

  1. Restful WebApi项目开发实践

    前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...

  2. ABP源码分析三十五:ABP中动态WebAPI原理解析

    动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...

  3. 9.1.3 .net framework通过业务逻辑层自动生成WebApi的做法

    首先需要说明的是这是.net framework的一个组件,而不是针对.net core的.目前工作比较忙,因此.net core的转换正在编写过程中,有了实现会第一时间贴出来. 接下来进入正题.对于 ...

  4. C#进阶系列——WebApi 路由机制剖析:你准备好了吗?

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...

  5. WebApi Controller 分类

    前言 写这篇WebApi Controller分类一是把Contrller分类的解决方法说一说,再顺便把遇到的问题和解决方法聊一聊. 说实话第一次在项目中使用WebApi感觉非常的不顺手. 遇到的问题 ...

  6. ABP之动态WebAPI(一)

    ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHan ...

  7. ABP之动态WebAPI(二)

    HttpControllerDescriptor与HttpActionDescriptor HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以 ...

  8. WebApi深入学习--概述+路由查找

    如何创建Controller这里就不说了,只写一些可能是高阶知识的内容 关于WebApi的官方介绍及示例 http://www.asp.net/web-api/ 1.跨域 Asp.NET有专门的跨域扩 ...

  9. WebApi支持命名空间重名问题

    using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq; ...

随机推荐

  1. codevs 3164 质因数分解

    3164 质因数分解  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description (多数据)给出t个数,求出它的质因子个 ...

  2. [VueJS + Typescript] Decouple Dependencies Using IoC Containers in Vue with TypeScript and InversifyJS

    Using Object Oriented Programming, OOP, style allows us to apply Inversion of Control, IoC, and more ...

  3. 设计模式之外观模式(Facade)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  4. pojWindow Pains(拓扑排序)

    题目链接: 啊哈哈,点我点我 题意: 一快屏幕分非常多区域,区域之间能够相互覆盖,要覆盖就把属于自己的地方所有覆盖. 给出这块屏幕终于的位置.看这块屏幕是对的还是错的.. 思路: 拓扑排序,这个简化点 ...

  5. 二叉查找树(BST)

    二叉查找树(BST) 二叉查找树(Binary Search Tree)又叫二叉排序树(Binary Sort Tree),它是一种数据结构,支持多种动态集合操作,如 Search.Insert.De ...

  6. i18n国际化的例子

    这个可以点击菜单进行中英文切换,每次切换就可以改变sessionStorage.languge,进行改变i18n的参数lang的值,然后重新调用下就可以了. 工程结构: i18n--| |---css ...

  7. 在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析

    在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析 低成本的Blob存储是一个强大的.通用的Hadoop兼容Azure存储解决方式无缝集成HDInsight.通过Hadoop分布式 ...

  8. 通过java类文件识别JDK编译版本号

    类文件里第5,6.7,8四个字节是jDK版本信息.当中5,6为小版本:7,8为大版本. 大版本号号相应JDK版本号例如以下: JDK版本 7,8字节 JDK8 52(0x34) JDK7 51(0x3 ...

  9. C/C++一些库函数的实现

    1. 写出String的具体实现 类的定义: #include <iostream> #include <cstring> using namespace std; class ...

  10. POJ1279 Art Gallery 多边形的核

    POJ1279 给一个多边形 求它的核的面积 所谓多边形的核 是多边形中的一个点集 满足其中的点与多边形边上的点的连线全部在多边形中 用多边形的每一条边所在的直线去切整个坐标平面 得到的一个凸包就是核 ...