2012-09-11 132 views
13

我能夠成功註冊內的global.asax.cs自定義的路由處理(從IRouteHandler導出)爲Web API路線ALA:自定義路由處理程序

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

不過,我可以在嘗試爲集成測試API設置內存主機時,似乎找不到方法來執行此操作,當我調用HttpConfiguration.Routes.MapRoute時,我無法在返回的IHttpRoute上設置處理程序。

我應該這樣做不同(例如通過使用自定義的HttpControllerSelector)?我顯然希望在兩種情況下都以同樣的方式進行。

謝謝, 馬特

編輯:

所以我落得這樣做基本上採取從下面的建議,而是簡單地重寫HttpControllerDispatcher類,如下所示:

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); 
    } 
} 

回答

13

你是非常正確。自主主機返回IHttpRoute並將HttpMessageHandler作爲參數。似乎沒有內在的方式來專門化路由處理程序。

更新:要成爲一個更清楚一點

你應該幾乎可以肯定在利用旅途中HttpControllerSelector並實現自定義的一個...一個例子是。 http://netmvc.blogspot.co.uk/

下面是一個實驗位的,如果HttpControllerSelector不sufficent您對什麼都要求原因...

但是,正如你可以看到MapHttpRoute確實有HttpMessageHandler過載,所以你可以試驗這個... if the handler is NULL then it defaults to IHttpController,但你可以實現你自己的,並使用它來指揮正確的控制器... MVC框架似乎使用[HttpControllerDispatcher]here,所以借用一些代碼,你可以在這裏放置自己的控制器/路由選擇代碼您也可以訪問路線和選擇器,並可以自行調換。

這CustomHttpControllerDispatcher代碼是DEMO只...查找線路

//做一些定製來接你的控制器

也許有一個遊戲...

實施例路線:

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

例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); 
     } 
} 
+0

非常感謝馬克,我承認自己很新的的WebAPI框架的內部,你可以解釋爲什麼這種方法比提供定製IHttpControllerSelector到更好組態?它看起來像默認的HttpControllerDispatcher使用配置中定義的ControllerSelector來處理我正在尋找的工作。 – mattcole

+0

@mattcole我應該有一點更清楚對不起 - 我想確認你是正確的,我懷疑(你已經這樣做),你應該看看一個自定義的HttpControllerSelector http://netmvc.blogspot.co.uk /作爲首選項,如果你正在做的是轉發給控制器。我只是在想,或許你是在做比選擇控制器更多的東西,或許還想使用除控制器之外的其他處理程序等等...... CustomHttpControllerDispatcher的想法有點像玩具和實驗......抱歉不清楚。 –

+0

沒問題馬克,最後我用你建議的版本去了,因爲我實際上只改變了路徑值中的一些值,我只是覆蓋了SendAsync方法,完成了我的工作,然後讓管道繼續運行。 – mattcole