• 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这个接口来实现的。

    NameDescription
    System_CAPS_pubmethod 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.

    System_CAPS_pubmethod 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选择逻辑。

  • 相关阅读:
    3D酷炫翻牌效果
    鼠标的默认事件之oncontextmenu及其案例
    键盘事件之keyCode
    用js和jQuery分别实现选项卡功能
    js中事件的绑定与解绑:attachEvent/detachEvent、addEventListener/removeEventListener
    js中的键盘事件:onkeydown、onkeypress、onkeyup
    用javaDBF操作(读、写)DBF文件
    Linux-tar命令
    动态查询
    java中对list进行分页显示数据到页面
  • 原文地址:https://www.cnblogs.com/Code-life/p/7182558.html
Copyright © 2020-2023  润新知