Переопределение поведения выбора контроллера/действия ASP.NET WebAPI

В большинстве ситуаций необходимости в изменении логики поиска контроллера/действия нет необходимости - с этим хорошо справляется существующая инфраструктура ASP.NET. Тем не менее, могут возникнуть ситуация, когда контроллеры расположены в другой сборке или выбор конкретного класса контроллера или его метода должны отличаться от правил, которые работают по умолчанию. ASP.NET WebAPI имеет возможность изменить это поведение в соответствии с логикой приложения.

Основные точки расширения для управления этим поведением, на которые стоит обратить внимание - интерфейсы IAssembliesResolver, IHttpControllerSelector, IHttpActionSelector.

Поиск контроллера

Стандартное поведение ASP.NET WebAPI при поиске контроллера - это найти класс, имя которого состоит из имени запрашиваемого контроллера и Controller. Этот класс также должен быть наследником базового класса ApiController.

Если требуется переопределить это поведение, следует реализовать сервис IHttpControllerSelector:

public class CustomControllerSelector : DefaultHttpControllerSelector
{
  private readonly HttpConfiguration _configuration;

  public CustomControllerSelector(HttpConfiguration configuration)
      : base(configuration)
  {
    _configuration = configuration;
  }

  public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
  {
    string controllerName;
    Type controllerType;

    // ...

    return new HttpControllerDescriptor(_configuration, controllerName, controllerType);
  }
}

В методе SelectController() должна быть определена логика поиска контроллера в приложении. Чтобы использовать этот объект нужно заменить соответствующий сервис в инфраструктуре ASP.NET WebAPI:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));

Поиск действия контроллера

ASP.NET WebAPI позволяет также переопределить логику поиска действия контроллера. Для этого следует создать отдельный сервис, реализующий IHttpActionSelector:

public class CustomActionSelector : ApiControllerActionSelector
{
  public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
  {
    var controller = controllerContext.ControllerDescriptor;
    var controllerType = controller.ControllerType;

    MethodInfo action;

    // ...

    return new ReflectedHttpActionDescriptor(controller, action);
  }
}

В методе SelectAction() производится поиск метода, который будет выбран в качестве действия контроллера. Используя рефлексию, нужно сообщить инфраструктуре какой именно метод следует использовать. Замена сервиса ASP.NET WebAPI для поиска действий:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    config.Services.Replace(typeof(IHttpActionSelector), new CustomActionSelector());