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 ...
随机推荐
- 初入Spring-boot(三)
Spring boot 的运行原理 Spring boot关于自动配置的源码在spring-boot-autoconfigure-xxxx.jar内. 一.可以通过下面三种方式查看当前项目中已启用和未 ...
- 关于ENABLE_BITCODE
pod 'TSVoiceConverter' 如果,设置了工程target的ENABLE_BITCODE为NO.但是,在真机上运行时,仍然提示类似于如下错误: URGENT: all bitcode ...
- Java中遍历map的四种方法 - 转载
在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...
- 使用ConcurrentLinkedQueue惨痛的教训
服务端原本有个定时任务对一个集合ArrayList 中的消息做处理. 因为考虑到处理消息是先进先出原则,所以优化的时候考虑改用ConcurrentLinkedQueue 当时没仔细深入研究过这个集合就 ...
- srm开发(基于ssh)(4)
1 input处理内容补充 -在struts2里面有错误处理机制,当上传文件超过默认的大小,自动返回结果input -在struts.xml中配置input的返回结果 <!-- 配置input结 ...
- JavaScript面向对象之Prototypes和继承
本文翻译自微软的牛人Scott Allen Prototypes and Inheritance in JavaScript ,本文对到底什么是Prototype和为什么通过Prototype能实现继 ...
- 【C#笔札】1 string类型
C中没有string这个类型,而是用字符串数组来实现,相对来说比较麻烦. LABVIEW相对来说要简单太多,毕竟他主要的精力集中在硬件控制上,软件操作方面极其简单. C#类似,C#中有System.S ...
- 20165332 学习基础和C语言基础调查
学习基础和c语言基础调查 一.技能学习经验 从小学过很多东西,架子鼓.电子琴.街舞.吉他.书法.美术......爱好也有很多,乒乓球.篮球.唱歌......这么多项技能,要说那一项比大多数人好,还真的 ...
- debug.js中的length的错误
记得昨天报了一个错,debug.js文件中的length未定义.前台不定位代码,后天也不报错,而debug.js是框架封装的文件,不是自己写的,无从得知是哪里的问题,而项目也已经重新启动过,无法撤销. ...
- 兄弟ifream的方法调用
兄弟ifream A var ifreamId = window.frameElement && window.frameElement.id || ''; var url = 'ur ...
