Пользовательский ApiExplorer с ApiControllers на основе пространства имен

Я пытаюсь добавить документацию по API в свою серверную систему. Страница ApiExplorer и справки по умолчанию работала отлично до того момента, пока я не представил версии для своих контроллеров Api.

Чтобы добавить версии, я создал подпапки в папке Controllers:

  • v1
  • v2
  • v3

и иметь там контроллеры Api на основе версий. Чтобы мой API можно было обнаружить, мне нужно переписать DefaultHttpControllerSelector, чтобы учесть пространства имен, предоставленные любым клиентом, и сопоставить их с правильными контроллерами:

Это сломало мой ApiExplorer по умолчанию, и следующее свойство возвращает ZERO описания API

Configuration.Services.GetApiExplorer().ApiDescriptions

Как я могу настроить существующий ApiExplorer и помочь ему найти мои контроллеры Api, а не переписывать всю реализацию ApiExplorer. Мне действительно нужно просто показать, где найти мои контроллеры API.

Пожалуйста, порекомендуйте.


person Alexey Strakh    schedule 10.02.2014    source источник
comment
Я пытаюсь сделать то же самое... Есть ли шанс, что вы поняли, как это реализовать?   -  person Saaman    schedule 24.02.2014
comment
Я ответил на ваш вопрос ниже   -  person Alexey Strakh    schedule 27.02.2014
comment
Большое спасибо! Я попробую это решение.   -  person Saaman    schedule 05.03.2014


Ответы (3)


Я покажу вам, как это сделать. Этот код предназначен только для обучения. Здесь я не говорю о дизайне и лучших практиках, поэтому не стесняйтесь менять все, что хотите.

Ну, вы должны выполнить следующие шаги:

1) Создайте собственный ApiExplorer:

public class MyApiExplorer: ApiExplorer
{
    private readonly string _version;

    public MyApiExplorer(string version) : base(GlobalConfiguration.Configuration)
    {
        _version = version != null ? version.ToUpperInvariant() : "V1";

        foreach(var apiDescription in ApiDescriptions)
        {
            apiDescription.RelativePath = apiDescription.RelativePath.Replace("{version}", _version);
        }

    }

    public override bool ShouldExploreController(string controllerVariableValue, HttpControllerDescriptor controllerDescriptor,
        IHttpRoute route)
    {
        return controllerDescriptor.ControllerType.FullName.Contains(_version);
    }

}

а) В конструкторе _версия будет преобразована в верхний регистр (на всякий случай, если он будет передан как нижний регистр), но если он равен нулю, то по умолчанию будет использоваться V1. Затем измените относительный путь, чтобы показать конкретную версию вместо {версия}.

b) ShouldExploreController (короткими словами) решает, берется ли конкретный контроллер для отображения в документации. В этом случае мы будем показывать только те контроллеры, полное название которых содержит выбранную версию.

2) Перейдите в класс HelpController и измените метод Index следующим образом:

public ActionResult Index(string version)
{
    //...

    Configuration.Services.Replace(typeof(IApiExplorer), new MyApiExplorer(version));

    return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}

Мы заменяем текущий ApiExplorer своим собственным, чтобы он возвращался при вызове Configuration.Services.GetApiExplorer().

Теперь вы можете использовать это .../help?version=v1 или .../help?version=v2 или .../help?version=v3, и вы получите конкретную документацию по контроллеру API.

person foxhard    schedule 07.04.2015
comment
Твердый. Спасибо за инструкцию! - person Kevin; 25.08.2015
comment
Не лучше ли поместить Configuration.Services.Replace в статический ctor для HelpController? В противном случае это будет вызываться каждый раз. - person John Zabroski; 21.04.2016

Оказалось, что ApiExplorer здесь ни при чем. Вместо этого вы должны изменить свой селектор контроллера на основе пространства имен:

NamespaceHttpControllerSelector : DefaultHttpControllerSelector
{
//...
    public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() 
    {
        var mapping = base.GetControllerMapping();
        mapping["User"] = new HttpControllerDescriptor
        {
            Configuration = _httpConfig,
            ControllerName = "User",
            ControllerType = typeof(UserController)
        };
        //...
        return mapping;
    }
    //...  }

То есть. После этого по умолчанию ApiExplorer найдет вам контроллеры и выберет все действия.

person Alexey Strakh    schedule 24.02.2014

Недавно я столкнулся с похожей проблемой и решил ее следующим образом: 2 LOC:

public class VersionControllerSelector : IHttpControllerSelector

to

public class VersionControllerSelector : DefaultHttpControllerSelector

...а также...

public VersionControllerSelector(HttpConfiguration config)

to

public VersionControllerSelector(HttpConfiguration config) : base(config)
person Stachu    schedule 15.04.2014