Содержание
До сих пор мы разрабатывали нашы проекты ASP.NET Core Web API, особенно не вдаваясь в вопросы документирования тех или иных возможностей и функций приложения. Между тем, документирование API – это, едва ли не самая важная часть работы над проектом, если вы планируете его распространять среди широкого круга пользователей. Именно документация API позволяет потенциальным и уже имеющимся пользователям разобраться с тем, как работает ваш API, какие методы предоставляет, как его эффективно использовать и так далее.
Что такое Swagger и OpenAPI?
OpenAPI — это не зависящая от языка спецификация для описания REST API. В 2015 году OpenAPI Initiative был передан проект под названием Swagger – инструментарий для описания API с использованием спецификации OpenAPI. На сегодняшний день эти два названия – OpenAPI и Swagger стали на столько тесно связанными, что их можно даже назвать взаимозаменяемыми. Даже в разделе официального сайта Microsoft, посвященному работе со Swagger первое же предложение начинается со слов «Swagger (OpenAPI) – это спецификация…», хотя, если быть предельно строгими к описанию, то спецификацией является OpenAPI, а Swagger – всего лишь инструмент для работы в соответствии с этой спецификацией, хотя и довольно мощный, и удобный.
Nuget-пакеты для Swagger
В ASP.NET Core существует две реализации OpenAPI – это Swashbuckle и NSwag. Причем, по умолчанию, при создании проекта ASP.NET Core Web API используется именно первая реализация.
Swagger в ASP.NET Core использует три компонента:
- AspNetCore.Swagger – содержит объектную модель Swagger и промежуточное программное обеспечение для предоставления объектов SwaggerDocument в формате JSON.
- AspNetCore.SwaggerGen – генератор Swagger, который создает объекты SwaggerDocument непосредственно из наших маршрутов, контроллеров и моделей.
- AspNetCore.SwaggerUI – встроенная версия инструмента пользовательского интерфейса Swagger. Он интерпретирует Swagger JSON для создания богатых и настраиваемых возможностей описания функций веб-API.
Для того, чтобы воспользоваться всеми этими компонентами, нам необходимо установить nuget-пакет Swashbuckle.AspNetCore. После установки пакета в «Обозревателе решений» Visual Studio проект будет выглядеть следующим образом
Настройка Swagger в приложении
Настроим работу Swagger в нашем приложении. Для этого перейдем в файл Program.cs и внесем в него следующие изменения
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddSwaggerGen(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseSwagger(); app.UseSwaggerUI(); app.UseAuthorization(); app.MapControllers(); app.Run();
Здесь мы подключаем необходимый сервис для генерации документов Swagger
builder.Services.AddSwaggerGen();
и встраиваем два компонента middleware в конвейер обработки запросов.
app.UseSwagger(); app.UseSwaggerUI();
При этом мы оставляем все настройки Swagger со значениями по умолчанию. Теперь запустим приложение, откроем любой браузер и перейдем по адресу https://localhost:[port]/swagger/. В результате вы увидите Swagger UI, где в удобном виде будут сгруппированы все методы API, которые мы добавляли в наше приложение
Методы API сгруппированы по контроллерам. Также, в этом же окне представлены и все схемы данных, которые используются в приложении
Конечные точки Swagger
На данный момент пользовательский интерфейс Swagger доступен по адресу https://localhost:[port]/swagger/, а если вы перейдете по адресу https://localhost:[port]/swagger/v1/swagger.json, то увидите сформированный документ Swagger (см. рис):
Этот документ содержит описание всех методов API, созданное с использованием спецификации OpenAPI 3.0.1. При необходимости мы можем менять как расположение документа Swagger, так и адрес расположения пользовательского интерфейса. Например
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
Здесь в методе расширения UseSwaggerUI() мы добавили настройки – конечную точку расположения документа Swagger
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
А также указали для свойства RoutePrefix пустую строку, которая означает, что пользовательский интерфейс Swagger будет доступен по адресу https://localhost:[port].
Общие сведения об API
Также мы можем добавить общие сведения об API, используя настройки сервиса Swagger
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo()
{
Description = "Web API на основе контроллеров",
Title = "Web API v1",
Version = "v1",
Contact = new Microsoft.OpenApi.Models.OpenApiContact()
{
Email = "admin@webdelphi.ru",
Name = "Vlad",
Url = new Uri("https://csharp.webdelphi.ru")
}
});
});
Здесь мы добавили версия API, небольшое описание и контактные данные. В интерфейсе Swagger эта информация будет выглядеть следующим образом
Настройка авторизации
Для того, чтобы использовать механизмы авторизации при тестировании запросов к API в Swagger необходимые настройки авторизации также добавляются при регистрации сервиса в контейнере зависимостей. Например, добавим авторизацию с использованием JWT-токенов, которую мы создавали ранее для нашего приложения
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo()
{
Description = "Web API на основе контроллеров",
Title = "Web API v1",
Version = "v1",
Contact = new Microsoft.OpenApi.Models.OpenApiContact()
{
Email = "admin@webdelphi.ru",
Name = "Vlad",
Url = new Uri("https://csharp.webdelphi.ru")
}
});
//настройки авторизации
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "Скопируйте сюда ключ доступа и добавьте в начале строку \"Bearer\"",
In = ParameterLocation.Header,
Scheme = "Bearer",
Type = SecuritySchemeType.ApiKey,
Name = "Authorization"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference()
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Name = "Bearer",
},
new List<string>()
}
});
});
Здесь мы определяем способ авторизации
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "Скопируйте сюда ключ доступа и добавьте в начале строку \"Bearer\"",
In = ParameterLocation.Header,
Scheme = "Bearer",
Type = SecuritySchemeType.ApiKey,
Name = "Authorization"
});
указав место расположения ключа доступа (ParameterLocation.Header – заголовок), имя схемы авторизации, которое должно использоваться в заголовке («Bearer»), тип схемы безопасности (SecuritySchemeType.ApiKey), имя заголовка в котором будет размещаться ключ безопасности («Authorization»), а также подсказку для клиента API. И далее мы добавили объект, определяющий требования безопасности.
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference()
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Name = "Bearer",
},
new List<string>()
}
});
Здесь имя объекта полностью соответствует имени схемы, которое мы определили выше при описании способа авторизации. Теперь, если запустить приложение и открыть в браузере Swagger UI, то мы должны увидеть следующее изменение в интерфейсе
Для того, чтобы авторизоваться в Swagger UI для выполнения запросов к API, необходимо нажать кнопку Authorize и ввести ключ доступа:
После этого можно выбрать в списке какой-либо метод API, требующий авторизации и выполнить его.
Добавление описания методов API
Swagger – это не столько инструмент для тестирования методов API, сколько инструмент для документирования API. Однако, на данный момент, из всей документации по API у нас только его краткое описание. Исправим этот момент, позволив Swagger создавать документацию по API, используя XML-комментарии в коде. Для этого перейдем в свойства проекта в Visual Studio, кликнув правой кнопкой мыши по его названию в обозревателе решений
В разделе «Сборка —> Выходные данные» необходимо установить флажок напротив пункта «Файл документации» и указать имя XML-файла в котором будет храниться документация по API
Теперь нам необходимо настроить Swagger на использование этого файла. Сделать это можно так же, как и настройку авторизации – при добавлении сервиса
builder.Services.AddSwaggerGen(options =>
{
//добавление общих сведений о приложении
//тут код настройки общих сведений
//настройки авторизации
//тут код настройки авторизации
//настраиваем Swagger на чтение XML-комментариев
var xmlPath = Path.Combine(Environment.CurrentDirectory, "documentation.xml");
options.IncludeXmlComments(xmlPath);
});
Чтобы не повторять уже рассмотренный выше код настройки сервиса, здесь показаны только новые строки кода, в которых мы указываем для Swagger путь к файлу с XML-комментариями.
Теперь перейдем к какому-нибудь контроллеру API и создадим документацию. Например, откроем файл WeatherForecastController, поставим курсор мыши над методом Get() и трижды нажмем на клавиатуре «/» (слэш). В результате сгенерируется стандартный шаблон описания метода
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Добавим описание метода.
/// <summary>
/// Возвращает прогноз погоды на пять дней
/// </summary>
/// <returns>Список обхектов WeatherForecast</returns>
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Теперь запустим приложение и откроем в браузере Swagger UI
Похожим образом мы можем добавлять описания для параметров методов, если они используются в действии контроллера.
Также при описании Web API важно предоставлять информацию не только о параметрах методов и их назначении, но и о том, какие коды статуса HTTP может возвращать тот или иной метод и что эти коды означают для пользователя. Чтобы добавить описание возвращаемых кодов статуса для метода используется специальный атрибут [ProducesResponseType], а в XML-комментарии <response code=”код_статуса”>, например
/// <summary>
/// Возвращает прогноз погоды на пять дней
/// </summary>
/// <returns>Список обхектов WeatherForecast</returns>
/// <response code="200">Запрос на добавление новой роли успешно выполнен</response>
/// <response code="400">Ошибка выполнения запроса</response>
[HttpGet]
[ProducesResponseType(typeof(IdentityResult), 200, "application/json")]
[ProducesResponseType(typeof(ProblemDetails), 400, "application/json")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Здесь мы использовали атрибут ProducesResponseType с тремя параметрами – тип возвращаемого результата, код статуса HTTP, тип данных в теле ответа. Обязательным из этих параметров является только код статуса. Теперь запустим приложение и посмотрим на описание кодов статуса для метода в Swagger UI
Аналогичным образом, используя XML-комментарии, мы можем добавлять описание для свойств моделей, используемых в API, а также использовать аннотации данных для указания обязательных полей (свойств) модели.
Тестирование API в Swagger UI
С помощью Swagger UI мы можем тестировать запросы к API. Для этого необходимо раскрыть вкладку с необходимым методом, например, как показано на рисунке выше, а затем последовательно нажать кнопки «Try It Out» и «Execute». Если же метод API подразумевает отправку каких-либо данных или использование параметров запроса, то их также необходимо предварительно заполнить в соответствующих полях. Ниже представлен результат выполнения метода Get() контроллера WeatherForecastController.
Итого
Для документирования API в ASP.NET Core мы можем использовать инструмент Swagger, который умеет работать с документацией в коде приложения. При необходимости, мы можем настроить Swagger UI для работы с методами, для которых требуется авторизация, например, с использованием JWT-токенов.











