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

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

Для добавления версий я создал подпапки в папке Controllers:

  • v1
  • v2
  • v3

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

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

Configuration.Services.GetApiExplorer().ApiDescriptions

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

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

3 ответа

Решение

Оказалось, что тут нет ничего общего с 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 найдет вам контроллеры и загрузит все действия.

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

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

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

}

a) В конструкторе _version будет преобразован в upperCase (на всякий случай, если он будет передан как lowerCase), но если он имеет значение null, то по умолчанию будет использоваться V1. Затем измените относительный путь, чтобы показать конкретную версию вместо {версия}.

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

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.

Я недавно столкнулся с подобной проблемой, и решил мою с этим: 2 LOC:

public class VersionControllerSelector : IHttpControllerSelector

в

public class VersionControllerSelector : DefaultHttpControllerSelector

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

public VersionControllerSelector(HttpConfiguration config)

в

public VersionControllerSelector(HttpConfiguration config) : base(config)
Другие вопросы по тегам