在ASP.Net的WebAPI自定义路由处理程序 [英] Custom route handlers in ASP.Net WebAPI

查看:233
本文介绍了在ASP.Net的WebAPI自定义路由处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能够成功注册内的global.asax.cs一个Web API路线ALA一个自定义的路由处理程序(从IRouteHandler派生):

  routes.MapHttpRoute(
            名称:DefaultApi
            routeTemplate:{}客户端{/api/1.0/控制器} / {行动} / {ID}
            默认:新{ID = UrlParameter.Optional}
        ).RouteHandler =新SingleActionAPIRouteHandler();

不过,我似乎无法找到一个方法来做到这一点在内存中的主机试图建立一个用于集成测试API时,当我打电话HttpConfiguration.Routes.MapRoute我不能设置一个处理器上返回IHttpRoute。

我应该(通过自定义HttpControllerSelector例如)不同的这样做呢?我明明喜欢做它在两种情况下是一样的。

谢谢,
马特

编辑:

所以我落得这样做基本上遵循从下面的建议,而是简单地覆盖HttpControllerDispatcher类,如下所示:

 公共类CustomHttpControllerDispatcher:HttpControllerDispatcher
{
    公共CustomHttpControllerDispatcher(HttpConfiguration配置):基地(配置)
    {
    }
    保护覆盖任务< Htt的presponseMessage> SendAsync(HTT prequestMessage请求的CancellationToken的CancellationToken)
    {
        //我在这里的东西        返回base.SendAsync(请求的CancellationToken);
    }
}


解决方案

您是非常正确的。自主机返回IHttpRoute并采取HttpMessageHandler作为参数。似乎没有内在的办法特异性的路由处理。

更新:要成为一个更清楚一点

您应该几乎可以肯定在使用HttpControllerSelector和实现一个自定义...一个例子是一展身手。 http://netmvc.blogspot.co.uk/

下面是一个实验位如果HttpControllerSelector不sufficent你要求什么都...原因

但是,正如你可以看到 MapHttpRoute 确实有 HttpMessageHandler 过载,所以你可以用这个实验。 .. <一href=\"http://msdn.microsoft.com/en-us/library/system.web.http.routing.ihttproute.handler%28v=vs.108%29.aspx\">if处理程序为NULL,则默认为IHttpController ,但你可以实现你自己的,并以此来引导到正确的控制器...... MVC框架似乎使用 [HttpControllerDispatcher] here,所以借用一些code,你可以在这里把你自己的控制器/路由选择code太 - 你有机会获得途径和选择,并可以进出自己掉它

这CustomHttpControllerDispatcher code是DEMO只...查找行


  

//做一些定制来接你的控制器


也许有一个戏......

示例路线:

  config.Routes.MapHttpRoute(
            名称:DefaultApi
            routeTemplate:API / {}控制器/(编号),
            默认:新{ID = RouteParameter.Optional},
            约束:空,
            处理:新CustomHttpControllerDispatcher(配置)
        );

示例CustomHttpControllerDispatcher:

 公共类CustomHttpControllerDispatcher:HttpMessageHandler
{
        私人IHttpControllerSelector _controllerSelector;
        私人只读HttpConfiguration _configuration;        公共CustomHttpControllerDispatcher(HttpConfiguration配置)
        {
            _configuration =配置;
        }        公共HttpConfiguration配置
        {
            {返回_configuration; }
        }        私人IHttpControllerSelector ControllerSelector
        {
            得到
            {
                如果(_controllerSelector == NULL)
                {
                    _controllerSelector = _configuration.Services.GetHttpControllerSelector();
                }
                返回_controllerSelector;
            }
        }        保护覆盖任务&LT; Htt的presponseMessage&GT; SendAsync(HTT prequestMessage请求的CancellationToken的CancellationToken)
        {
                返回SendAsyncInternal(请求的CancellationToken);
        }        私人任务&LT; Htt的presponseMessage&GT; SendAsyncInternal(HTT prequestMessage请求的CancellationToken的CancellationToken)
        {            IHttpRouteData的RouteData = request.GetRouteData();
            Contract.Assert(的RouteData!= NULL);            //做一些定制来接你的控制器
            HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(请求);
            IHttpController httpController = httpControllerDescriptor.CreateController(请求);            //创建上下文
            HttpControllerContext controllerContext =新HttpControllerContext(_configuration,的RouteData,请求);
            controllerContext.Controller = httpController;
            controllerContext.ControllerDescriptor = httpControllerDescriptor;            返回httpController.ExecuteAsync(controllerContext,的CancellationToken);
        }
}

I'm able to successfully register a custom route handler (deriving from IRouteHandler) inside global.asax.cs for a Web API route ala:

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{client}/api/1.0/{controller}/{action}/{id}",
            defaults: new{id = UrlParameter.Optional}
        ).RouteHandler = new SingleActionAPIRouteHandler();

However I can't seem to find a way to do this when trying to setup an in memory host for the API for integration testing, when I call HttpConfiguration.Routes.MapRoute I'm not able to set a handler on the returned IHttpRoute.

Should I be doing this differently (for instance by using a custom HttpControllerSelector)? I'd obviously like to do it the same way in both cases.

Thanks, Matt

EDIT:

So what I ended up doing was basically following the advice from below, but simply overriding the HttpControllerDispatcher class as follows:

public class CustomHttpControllerDispatcher : HttpControllerDispatcher
{
    public CustomHttpControllerDispatcher(HttpConfiguration configuration) : base(configuration)
    {
    }
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // My stuff here

        return base.SendAsync(request, cancellationToken);
    }
}

解决方案

You are very right. Self host returns IHttpRoute and takes HttpMessageHandler as a parameter. There seems no inbuilt way to specificity a route handler.

Update: To be a bit clearer

You should almost certainly have a go at using a HttpControllerSelector and implementing a custom one... An example being. http://netmvc.blogspot.co.uk/

What follows is a bit of experimentation if the HttpControllerSelector is not sufficent for your requirements for what ever reason...

But, as you can see the MapHttpRoute does have an overload for HttpMessageHandler so you can experiment with this... if the handler is NULL then it defaults to IHttpController but you can implement your own and use this to direct to the correct controller... The MVC framework appears to use [HttpControllerDispatcher] here, so borrowing some code you can place your own controller / route selection code here too - you have access to the route and selector and can swap it in and out yourself.

This CustomHttpControllerDispatcher code is for DEMO only... look for the line

//DO SOMETHING CUSTOM HERE TO PICK YOUR CONTROLLER

And perhaps have a play with that...

Example route:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: null,
            handler: new CustomHttpControllerDispatcher(config)
        );

Example CustomHttpControllerDispatcher:

public class CustomHttpControllerDispatcher : HttpMessageHandler
{
        private IHttpControllerSelector _controllerSelector;
        private readonly HttpConfiguration _configuration;

        public CustomHttpControllerDispatcher(HttpConfiguration configuration)
        {
            _configuration = configuration;
        }

        public HttpConfiguration Configuration
        {
            get { return _configuration; }
        }

        private IHttpControllerSelector ControllerSelector
        {
            get
            {
                if (_controllerSelector == null)
                {
                    _controllerSelector = _configuration.Services.GetHttpControllerSelector();
                }
                return _controllerSelector;
            }
        }

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
                return SendAsyncInternal(request, cancellationToken);
        }

        private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            IHttpRouteData routeData = request.GetRouteData();
            Contract.Assert(routeData != null);

            //DO SOMETHING CUSTOM HERE TO PICK YOUR CONTROLLER
            HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(request);
            IHttpController httpController = httpControllerDescriptor.CreateController(request);

            // Create context
            HttpControllerContext controllerContext = new HttpControllerContext(_configuration, routeData, request);
            controllerContext.Controller = httpController;
            controllerContext.ControllerDescriptor = httpControllerDescriptor;

            return httpController.ExecuteAsync(controllerContext, cancellationToken);
        }
}

这篇关于在ASP.Net的WebAPI自定义路由处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆