Как я могу сделать URL-адрес в Swashbuckle/Swaggerwork, когда api подан из другого проекта?

все. Я пытаюсь документировать WebApi 2 с помощью пакета Swashbuckle.

Все работает отлично, если API работает сам по себе, то есть localhost/api/swagger приводит меня в ui и localhost/api/swagger/docs/v1 в json.

Однако приложение producation инициализирует этот же проект Webapi, запустив метод webapiconfig этого проекта из global.asax.cs в другом - теперь веб-проекте (основное приложение). Таким образом, api url выглядит как localhost/web/api вместо localhost/api.

Теперь swashbuckle не работает так.

  • localhost/api/swagger генерирует ошибку, не может загрузить "API.WebApiApplication", ну конечно
  • localhost/web/swagger = 404
  • localhost/web/api/swagger = 404

Я пытался повсюду искать, но все, что я нашел, обходное решение.

c.RootUrl(req => req.RequestUri.GetLeftPart(UriPartial.Authority) + VirtualPathUtility.ToAbsolute("~/").TrimEnd('/'));

К сожалению, это не сработает, теперь, может быть, и должно, и мне просто нужно что-то изменить, но я даже не знаю, что именно ожидает это свойство и на что он должен быть установлен.

Может быть, это даже не применимо - возможно, у нас есть что-то другое или некоторые изменения кода swashbuckle.

Буду признателен за любую помощь, которую вы можете предоставить. Я действительно начинаю любить swagger (и swashbuckle) для документации для отдыха.

Ответ 1

Для Swashbuckle 5.x:

Это, по-видимому, задается методом расширения httpConfiguration с именем EnableSwagger. Swashbuckle 5.x readme отмечает, что это заменяет SwaggerSpecConfig. SwaggerDocConfig RootUrl() специально заменяет ResolveBasePathUsing() с 4.x.

Это практически работает так же, как и раньше, похоже, что самое большое изменение было в том, что оно было переименовано и перенесено в SwaggerDocConfig:

public void RootUrl(Func<HttpRequestMessage, string> rootUrlResolver)

Пример из readme, измененный для краткости:

string myCustomBasePath = @"http://mycustombasepath.com";

httpConfiguration
    .EnableSwagger(c =>
        {
            c.RootUrl(req => myCustomBasePath);

            // The rest of your additional metadata goes here
        });

Для Swashbuckle 4.x:

Используйте SwaggerSpecConfig ResolveBasePathUsing и попросите свою лямбда прочитать вашу известную конечную точку.

ResolveBasePathUsing:

public SwaggerSpecConfig ResolveBasePathUsing(Func<HttpRequestMessage, string> basePathResolver);

Мой API находится за балансировщиком нагрузки, и это было полезным решением для предоставления базового адреса. Вот глупый пример использования ResolveBasePathUsing для разрешения пути с известным базовым путем.

string myCustomBasePath = @"http://mycustombasepath.com";

SwaggerSpecConfig.Customize(c =>
{
    c.ResolveBasePathUsing((req) => myCustomBasePath);
}

Я четко определил конечную точку для ясности, но вы можете определить ее в любом месте. Вы даже можете использовать объект запроса, чтобы попытаться очистить свой uri запроса, чтобы указать на /web/api вместо /api.

Разработчик прокомментировал это обходное решение GitHub в прошлом году:

Лямбда принимает текущий HttpRequest (т.е. Запрос для данной Swagger ApiDeclaration) и должен возвращать строку, которая будет использоваться как baseUrl для вашего Api. Для приложений с балансировкой нагрузки это должно возвращать путь балансировки нагрузки.

Реализация по умолчанию выглядит следующим образом:

(req) => req.RequestUri.GetLeftPart(UriPartial.Authority) +  req.GetConfiguration().VirtualPathRoot.TrimEnd('/');

...

Re относительные пути, спецификация Swagger требует абсолютных путей, потому что URL-адрес, на котором выполняется Swagger, не обязательно должен быть URL-адресом фактического API.

...

Лямбда передается экземпляр HttpRequestMessage... вы должны иметь возможность использовать это для доступа к RequestUri и т.д. Другой вариант: вы можете просто поместить имя хоста в ваш web.config и попросить лямбда просто прочитать его оттуда.