WebApi实现IHttpControllerSelector问题
一.让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问题的更多相关文章
- Restful WebApi项目开发实践
前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...
- ABP源码分析三十五:ABP中动态WebAPI原理解析
动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...
- 9.1.3 .net framework通过业务逻辑层自动生成WebApi的做法
首先需要说明的是这是.net framework的一个组件,而不是针对.net core的.目前工作比较忙,因此.net core的转换正在编写过程中,有了实现会第一时间贴出来. 接下来进入正题.对于 ...
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗?
前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...
- WebApi Controller 分类
前言 写这篇WebApi Controller分类一是把Contrller分类的解决方法说一说,再顺便把遇到的问题和解决方法聊一聊. 说实话第一次在项目中使用WebApi感觉非常的不顺手. 遇到的问题 ...
- ABP之动态WebAPI(一)
ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHan ...
- ABP之动态WebAPI(二)
HttpControllerDescriptor与HttpActionDescriptor HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以 ...
- WebApi深入学习--概述+路由查找
如何创建Controller这里就不说了,只写一些可能是高阶知识的内容 关于WebApi的官方介绍及示例 http://www.asp.net/web-api/ 1.跨域 Asp.NET有专门的跨域扩 ...
- WebApi支持命名空间重名问题
using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq; ...
随机推荐
- codevs 3164 质因数分解
3164 质因数分解 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description (多数据)给出t个数,求出它的质因子个 ...
- [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 ...
- 设计模式之外观模式(Facade)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- pojWindow Pains(拓扑排序)
题目链接: 啊哈哈,点我点我 题意: 一快屏幕分非常多区域,区域之间能够相互覆盖,要覆盖就把属于自己的地方所有覆盖. 给出这块屏幕终于的位置.看这块屏幕是对的还是错的.. 思路: 拓扑排序,这个简化点 ...
- 二叉查找树(BST)
二叉查找树(BST) 二叉查找树(Binary Search Tree)又叫二叉排序树(Binary Sort Tree),它是一种数据结构,支持多种动态集合操作,如 Search.Insert.De ...
- i18n国际化的例子
这个可以点击菜单进行中英文切换,每次切换就可以改变sessionStorage.languge,进行改变i18n的参数lang的值,然后重新调用下就可以了. 工程结构: i18n--| |---css ...
- 在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析
在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析 低成本的Blob存储是一个强大的.通用的Hadoop兼容Azure存储解决方式无缝集成HDInsight.通过Hadoop分布式 ...
- 通过java类文件识别JDK编译版本号
类文件里第5,6.7,8四个字节是jDK版本信息.当中5,6为小版本:7,8为大版本. 大版本号号相应JDK版本号例如以下: JDK版本 7,8字节 JDK8 52(0x34) JDK7 51(0x3 ...
- C/C++一些库函数的实现
1. 写出String的具体实现 类的定义: #include <iostream> #include <cstring> using namespace std; class ...
- POJ1279 Art Gallery 多边形的核
POJ1279 给一个多边形 求它的核的面积 所谓多边形的核 是多边形中的一个点集 满足其中的点与多边形边上的点的连线全部在多边形中 用多边形的每一条边所在的直线去切整个坐标平面 得到的一个凸包就是核 ...