ASP.NET WebApi通过自定义ControllerSelector来自定义Controller的选择
在web api中,我们可以通过给Cotroller类添加RoutePrefixAttribute来定义url与Controller之间的映射,但是有时候有一些特殊情况下,我们需要做一些特殊处理来将某些即时满足某一url prefix的请求映射到另一个Controller.这种情况下,我们就需要自定义Controller的Selector逻辑了。
看一下这个如下两个Controller:
[RoutePrefix("Order")]
public class OrderController : ApiController
{
[HttpGet]
[Route("~/Product/Order")]
public List<string> GetOrder()
{
return new List<string>() { "p1", "p2" };
}
}
[RoutePrefix("Product")]
public class ProductController : ApiController
{
[HttpPost]
[Route("{id}")]
public string Get(string id,[FromBody]string product)
{
return "pbyid";
}
}
当用户访问/Product/Order这个url时,系统会产生错误,因为OrderController中的GetOrder action和ProductController 中的Get action都与该url匹配(即使这两个Action对应的Method是不一样的,但是当选择Controller的时候只会根据Url中与Controller中Route的匹配情况来选择,具体Controller选择算法参考官方文档)。其实根据我们对id规则的定义,Order这个字符不会是一个合法的id,因此这个Url肯定是应该映射到OrderController中的GetOrder action。(这里仅仅为了演示自定义Controller的选择,实际情况有更好的解决该问题的方法)
这个种情况下我们就需要自定义Controller的选择逻辑了。
首先我们看一下Web Api消息处理的整个流程图:

从这张图可以看到,处理请求时,web api会先根据url找到匹配的Controller,然后在创建的controller对象中去调用匹配的action方法。在上面的例子中,ProductController和OrderController都匹配请求url,所以会发生错误。我们在这个过程中加入自定义逻辑选择OrderController作为/Product/Order的Controller.问题就解决了。
从图中可以看到Controller的选择是通过IHttpControllerSelector这个接口来实现的。
| Name | Description | |
|---|---|---|
![]() |
GetControllerMapping() |
Returns a map, keyed by controller string, of all HttpControllerDescriptor that the selector can select. This is primarily called by IApiExplorer to discover all the possible controllers in the system. |
![]() |
SelectController(HttpRequestMessage) |
Selects a HttpControllerDescriptor for the given HttpRequestMessage. |
web api框架提供了这个接口的默认实现DefaultHttpControllerSelector.我们可以通过派生出自己的selector,然后重写SelectorController方法来自定义controller的选择逻辑。
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
//string controllerName = GetControllerName(request);
if (request.RequestUri.PathAndQuery.StartsWith("/Product/Order"))
{
if (_orderControllerDescriptor == null)
{
_orderControllerDescriptor = new HttpControllerDescriptor()
{
Configuration = _configuration,
ControllerName = typeof(OrderController).FullName,
ControllerType = typeof(OrderController)
};
} //return _orderControllerDescriptor;
} return base.SelectController(request);
}
然后在将自定义的selector注册到web api的对象容器中.
config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));
这样我们就将请求GET /Product/Order映射到了OrderController上,后续的Action Seletion会选择OrderController中的GetOrder方法来处理该请求。
采用相同的办法,我们也可以从默认的ActionSelector:ApiControllerActionSelector派生出自己的ActionSelector,然后重写SelectAction来自定义action选择逻辑。
ASP.NET WebApi通过自定义ControllerSelector来自定义Controller的选择的更多相关文章
- 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式
连表查询都用Left Join吧 最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...
- asp.net webapi自定义输出结果类似Response.Write()
asp.net webapi自定义输出结果类似Response.Write() [HttpGet] public HttpResponseMessage HelloWorld() { string ...
- ASP.NET WebApi OWIN 实现 OAuth 2.0(自定义获取 Token)
相关文章:ASP.NET WebApi OWIN 实现 OAuth 2.0 之前的项目实现,Token 放在请求头的 Headers 里面,类似于这样: Accept: application/jso ...
- ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver
ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver Message WebAPI作为通信架构必定包含包含请求与响应两个方法 ...
- 重温ASP.NET WebAPI(一)初阶
重温ASP.NET WebAPI(一)初阶 前言 本文为个人对WebApi的回顾无参考价值.主要简单介绍WEB api和webapi项目的基本结构,并创建简单地webaapi项目实现CRUD操作. ...
- 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) ASP.NET WebApi技术从入门到实战演练 C#面向服务WebService从入门到精通 DataTable与List<T>相互转换
路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中, ...
- ASP.NET WebApi 文档Swagger深度优化
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明博客园蜗牛原文地址,cnblogs.com/tdws 写在前面 请原谅我这个标题党,写到了第100篇随笔,说是深度优化,其实也并没有什么深度 ...
- ASP.NET WEBAPI 的身份验证和授权
定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...
- OData – the best way to REST–实例讲解ASP.NET WebAPI OData (V4) Service & Client
一.概念介绍 1.1,什么是OData? 还是看OData官网的简单说明: An open protocol to allow the creation and consumption of quer ...
随机推荐
- 启动工程Ehcache报错
缓存组建用的Ehcache,在启动的时候报了下面的错误,虽然不影响使用,看着还是有点碍眼: DEBUG net.sf.ehcache.util.UpdateChecker - Update che ...
- The revocation function was unable to check revocation for the certificate
https://stackoverflow.com/questions/45556189/git-the-revocation-function-was-unable-to-check-revocat ...
- 解决Spark用Maven编译时报Exception in thread "main" java.lang.OutOfMemoryError: PermGen space异常
异常截图: 解决方法: export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=512m"
- HDU 1159 Common Subsequence 动态规划
2017-08-06 15:41:04 writer:pprp 刚开始学dp,集训的讲的很难,但是还是得自己看,从简单到难,慢慢来(如果哪里有错误欢迎各位大佬指正) 题意如下: 给两个字符串,找到其中 ...
- tyvj 1091 等差数列 dp
P1091 等差数列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 广东汕头聿怀初中 Train#3 Problem 3 描述 等差数列的定义是一个数列S, ...
- vmware配置网卡
虚拟机网络配置 1. 启用VMWare虚拟网卡 如果没有查看到vmnet8这个网络连接,打开VMWare, 2. 设置虚拟机:选中安装好的虚拟机右键设置. 3. 设置虚拟机系统. 指令:vi /etc ...
- 通过Google Custom Search API 进行站内搜索
今天突然想把博客的搜索改为google的站内搜索,印象中google adsense中好像提高这个站内搜索的代码,但苦逼的是google adsense帐号一直审核不通过,所以只能通过google c ...
- pycharm(v 2018.1)新建工程没有导入本地包
新版的pycharm默认新建的工程Virtualenv(虚拟的环境),在创建环境时一定要注意勾选 Inherit global site-packages: 导入本地包 Make available ...
- DCGAN、WGAN、WGAN-GP、LSGAN、BEGAN原理总结及对比
DCGAN.WGAN.WGAN-GP.LSGAN.BEGAN原理总结及对比 from:https://blog.csdn.net/qq_25737169/article/details/7885778 ...
- tomcat映射物理路径
<Context path="/woyoubaoweb/upload" docBase="/opt/file/image/woyoubaoweb/upload&qu ...
