2012-09-11 26 views
13

soy capaz de registrar correctamente un controlador de ruta personalizada (que deriva de IRouteHandler) en el interior global.asax.cs para un ala ruta Web API:manipuladores de ruta personalizada en ASP.Net WebAPI

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

Sin embargo, puedo Parece que no hay forma de hacerlo cuando intento configurar un host en memoria para la API para las pruebas de integración. Cuando llamo a HttpConfiguration.Routes.MapRoute, no puedo configurar un controlador en IHttpRoute devuelto.

¿Debo hacer esto de otra manera (por ejemplo, usando un HttpControllerSelector personalizado)? Obviamente, me gustaría hacerlo de la misma manera en ambos casos.

Gracias, Matt

EDIT:

Así que lo que terminó haciendo fue básicamente siguiendo el consejo desde abajo, sino simplemente reemplazando la clase HttpControllerDispatcher de la siguiente manera:

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

Respuesta

13

Estás muy cierto. Self host devuelve IHttpRoute y toma HttpMessageHandler como parámetro. Parece que no existe un camino incorporado a la especificidad de un controlador de ruta.

Actualización: Para ser un poco más claro

Debe casi seguro que tienen un ir en el uso de un HttpControllerSelector e implementar uno personalizado ... Un ejemplo de ello. http://netmvc.blogspot.co.uk/

Lo que sigue es un poco de experimentación si el HttpControllerSelector no se sufficent para sus requisitos para cualquier razón ...

Pero, como se puede ver la MapHttpRoute tiene una sobrecarga de HttpMessageHandler por lo que puede experimentar con esto ... if the handler is NULL then it defaults to IHttpController pero puede implementar el suyo y usarlo para dirigirlo al controlador correcto ... Parece que el marco MVC usa [HttpControllerDispatcher]here, por lo que puede tomar su código de selección de controlador/ruta aquí. también - tiene acceso a la ruta y al selector y puede intercambiarlo usted mismo.

Este código es para CustomHttpControllerDispatcher demo sólo ... busque la línea

// hacer algo costumbre aquí para recoger a su CONTROLADOR

Y quizás tener un juego con eso ...

Ejemplo ruta:

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

Ejemplo 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

Muchas gracias Marcos, voy a admitir que soy bastante nuevo en la parte interna del marco WebAPI, ¿podría explicar por qué este enfoque es mejor que el suministro de una costumbre a la IHttpControllerSelector ¿configuración?Parece que HttpControllerDispatcher predeterminado usa ControllerSelector definido en la configuración para encargarse del trabajo que estoy buscando hacer. – mattcole

+0

@mattcole Debería haberlo tenido un poco más claro, quería confirmar que está en lo cierto y sospecho (como ya lo hizo) que debería echarle un vistazo a HttpControllerSelector personalizado http://netmvc.blogspot.co.uk/como preferencia si todo lo que estás haciendo es reenviar a un controlador. Solo pensaba que tal vez estabas haciendo algo más que elegir controladores y quizás querías usar otros controladores además del controlador, etc ... La idea de CustomHttpControllerDispatcher fue un poco de juguete y experimento ... lo siento por no ser más claro. –

+0

No hay problema Mark, al final fui con una versión de lo que sugirió, ya que solo estaba cambiando algunos valores en los valores de ruta, simplemente anulé el método SendAsync, hice mi trabajo y luego dejé que la tubería continuara en su camino. – mattcole

Cuestiones relacionadas