一.让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. 七牛云上传图片到cdn,cdn返回的是一个只有图片的url

    如:

  2. Google Kaptcha验证码的使用

    原文:http://www.kailing.pub/article/index/arcid/92.html Kaptcha是什么? kaptcha 是谷歌开源的非常实用的验证码生成工具,基于Simpl ...

  3. android 深入浅出 群内“每日一问” 问答总结

    永远不变的就是变. 俗话说的好,环境改变人生. 常常面对的是一群积极奋进的人,那么你的心态和生活也会变的充满斗志.青春在于折腾,趁我们还年轻,拿出你的激情.踏着泪水载着梦,才干拥有自己的一片天空. 上 ...

  4. node-npm/yarn

    很多人对npm或yarn了解甚少吧,下面我介绍一下常用的yarn/npm所谓的包管理工具. 首先我先介绍一下,npm属于国外Google镜像(下载贼慢),yarn属于Facebook开发的. npm: ...

  5. 改动Centosserver主机名称

    1.暂时改动server主机名称: hostname myhost. myhost为你指定的主机名称. 2.永久性的改动主机名称 Centosserver安装好之后.默认的主机名为:localhost ...

  6. 使用shell分页读取600万+的MySQL数据脚本

    shell-mysql 脚本背景 因为要在Linux上.远程读取mysql的表的数据,然后做一定清洗后.把数据上传至Hadoop集群中,使用Java写吧,感觉太麻烦了.得在Win上开发好,还得打成ja ...

  7. ≪统计学习精要(The Elements of Statistical Learning)≫课堂笔记(三)

    照例文章第一段跑题,先附上个段子(转载的哦~): I hate CS people. They don't know linear algebra but want to teach projecti ...

  8. 基于Canvas的Char.js库使用

    Chart.js是基于Html5 Canvas的图表库. 官网:http://www.chartjs.org/ 參考文档:http://www.chartjs.org/docs/ 支持六种图表,相应源 ...

  9. javascript下获取guid或者UTC时间作为唯一值

    javascript下,有时出于需要,可以利用guid或UTC时间作为当前页面中的唯一值. 什么场景需要弄这个唯一值? 比如说,用easyUI的treegrid,添加新节点.在treegrid里面 , ...

  10. Noip模拟 Day6.12

    第一题:贪吃蛇(snake) 本题其实就是判断一个有向图中有没有环,做一次拓扑排序就可以了,如果所有点都入队了,就表示没有环,否则就有环.或者就是dfs一次,每个点只需要被访问一次,这样也是O(n)的 ...