在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的选择的更多相关文章

  1. 连表查询都用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%我不知道在 ...

  2. asp.net webapi自定义输出结果类似Response.Write()

    asp.net webapi自定义输出结果类似Response.Write()   [HttpGet] public HttpResponseMessage HelloWorld() { string ...

  3. ASP.NET WebApi OWIN 实现 OAuth 2.0(自定义获取 Token)

    相关文章:ASP.NET WebApi OWIN 实现 OAuth 2.0 之前的项目实现,Token 放在请求头的 Headers 里面,类似于这样: Accept: application/jso ...

  4. ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

    ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver   Message WebAPI作为通信架构必定包含包含请求与响应两个方法 ...

  5. 重温ASP.NET WebAPI(一)初阶

    重温ASP.NET WebAPI(一)初阶   前言 本文为个人对WebApi的回顾无参考价值.主要简单介绍WEB api和webapi项目的基本结构,并创建简单地webaapi项目实现CRUD操作. ...

  6. 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) ASP.NET WebApi技术从入门到实战演练 C#面向服务WebService从入门到精通 DataTable与List<T>相互转换

    路由其实也可以很简单-------Asp.net WebAPI学习笔记(一)   MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中, ...

  7. ASP.NET WebApi 文档Swagger深度优化

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明博客园蜗牛原文地址,cnblogs.com/tdws   写在前面 请原谅我这个标题党,写到了第100篇随笔,说是深度优化,其实也并没有什么深度 ...

  8. ASP.NET WEBAPI 的身份验证和授权

    定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...

  9. 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 ...

随机推荐

  1. Contest-hunter 暑假送温暖 SRM08

    01-07都没写...然后突然来写貌似有点突兀啊...不管了,难得前排记录一下... 吐槽一下赛制...不得不说很强... cf 套oi...很创新...不过还是兹磁ACM或者CF A-1 数据才2& ...

  2. JMS-activMq与spring进行整合

     对JMS做了一个简要介绍之后,接下来就讲一下Spring整合JMS的具体过程.JMS只是一个标准,真正在使用它的时候我们需要有它的具体实现,这里我们就使用Apache的activeMQ来作为它的实现 ...

  3. JDBC相关总结

    JDBC statement的相关总结 1.Statement.PreparedStatement和CallableStatement都是接口(interface). 2.Statement继承自Wr ...

  4. IOS-社会化分享

    一.如何实现社交分享 在iOS中,实现“社交分享”的方法 1.自己编写各个平台的分享代码(代码量较多)   2.利用iOS自带的Social.framework   3.利用第三方的分享框架 友盟分享 ...

  5. 条款24:如果所有的参数都需要类型转换,那么请为此采用non-member函数

    首先还是下面这个class; class Rational{ public: Rational(, ); int numurator() const; int denominator() const; ...

  6. 20165210 Java第四次实验报告

    20165210 实验四 Android程序设计 实验步骤 第24章:初识Android 任务一:完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学号 学 ...

  7. C#当中利用Attribute实现简易AOP

    首先看一段简单的代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } //来自UI层的调用 ...

  8. jsp的组成和执行过程

    jsp由以下五个组成: Html静态页面 指令:  <%@  xxx  %> 小脚本:<%   xxx   %> 表达式:<% =       %> 声明:  &l ...

  9. cannot be read or is not a valid ZIP file

    在eclipse下创建 maven 项目,运行 flowable 6.1.2 配置maven之后,下载相应的依赖库. 发现报错: Archive for required library: '/Use ...

  10. Activity的生命周期,BACK键和HOME对生命周期的影响

    下面这张图详细的描述了Activity的整个生命周期: 直接上代码,注意看注释: [java] view plaincopy public class HelloActivity extends Ac ...