Руководство по созданию веб-API с помощью ASP.NET Core
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 8 этой статьи.
Авторы: Рик Андерсон (Rick Anderson) и Кирк Ларкин (Kirk Larkin)
В этом руководстве описаны основы создания веб-API на основе контроллера, использующего базу данных. Еще одним подходом к созданию API в ASP.NET Core является создание минимальных API. Сведения о выборе между минимальными API и API на основе контроллера см. в обзоре API. Руководство по созданию минимального API см . в руководстве по созданию минимального API с помощью ASP.NET Core.
Обзор
В этом руководстве создается следующий API-интерфейс:
API | Description | Текст запроса | Текст ответа |
---|---|---|---|
GET /api/todoitems |
Получение всех элементов задач | нет | Массив элементов задач |
GET /api/todoitems/{id} |
Получение объекта по идентификатору | нет | Элемент задачи |
POST /api/todoitems |
Добавление нового элемента | Элемент задачи | Элемент задачи |
PUT /api/todoitems/{id} |
Обновление существующего элемента | Элемент задачи | нет |
DELETE /api/todoitems/{id} |
Удаление элемента | нет | нет |
На следующем рисунке показана структура приложения.
Необходимые компоненты
Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- В поле поиска введите Веб-API.
- Выберите шаблон Веб-API ASP.NET Core и нажмите кнопку Далее.
- В диалоговом окне Настроить новый проект присвойте проекту имя TodoApi и нажмите кнопку Далее.
- В диалоговом окне "Дополнительные сведения":
- Убедитесь, что платформа — .NET 8.0 (долгосрочная поддержка).
- Убедитесь, что флажок Use controllers (uncheck to use minimal APIs) (Использовать контроллеры (снимите этот флажок для использования минимальных API)) установлен.
- Убедитесь, что установлен флажок для включения поддержки OpenAPI.
- Нажмите кнопку создания.
Добавление пакета NuGet
Пакет NuGet необходимо добавить для поддержки базы данных, используемой в этом руководстве.
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Откройте вкладку Browse (Обзор).
- Введите Microsoft.EntityFrameworkCore.InMemory в поле поиска и щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Тестирование проекта
Шаблон проекта создает API WeatherForecast
с поддержкой Swagger.
Нажмите клавиши CTRL+F5, чтобы выполнить запуск без отладчика.
Visual Studio отображает следующее диалоговое окно, если проект еще не настроен для использования SSL:
Выберите Да, чтобы сделать SSL-сертификат IIS Express доверенным.
Отобразится следующее диалоговое окно.
Выберите Да, если согласны доверять сертификату разработки.
Сведения о доверии к браузеру Firefox см. в разделе Ошибка сертификата браузера Firefox SEC_ERROR_INADEQUATE_KEY_USAGE.
Visual Studio запускает браузер по умолчанию и переходит https://localhost:<port>/swagger/index.html
в папку, где <port>
выбран случайный номер порта при создании проекта.
Откроется страница Swagger /swagger/index.html
. Выберите Get (Получить)>Try it out (Попробовать)>Execute (Выполнить). На странице отобразятся:
- команда Curl для тестирования API WeatherForecast;
- URL-адрес для тестирования API WeatherForecast;
- код, текст и заголовки ответа;
- Раскрывающийся список с типами носителей и примером значения и схемы.
Если страница Swagger не отображается, см. эту проблему на сайте GitHub.
Swagger используется для создания полезной документации и страниц справки для веб-API. В этом руководстве используется Swagger для тестирования приложения. Дополнительные сведения о Swagger см. в статье Документация по веб-API ASP.NET Core с использованием Swagger (OpenAPI).
Скопируйте и вставьте URL-адрес запроса в адресную строку браузера: https://localhost:<port>/weatherforecast
Возвращаемые данные JSON будут примерно такими:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
Добавление класса модели
Модель — это набор классов, представляющих данные, которыми управляет приложение. Для этого приложения используется класс модели TodoItem
.
- В обозревателе решений щелкните проект правой кнопкой мыши. Выберите Добавить>Новая папка. Назовите папку
Models
. - Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Присвойте классу имя TodoItem и выберите Добавить. - Замените код шаблона следующим кодом:
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Свойство Id
выступает в качестве уникального ключа реляционной базы данных.
Классы моделей можно размещать в любом месте проекта, но обычно для этого используется папка Models
.
Добавление контекста базы данных
Контекст базы данных —это основной класс, который координирует функциональные возможности Entity Framework для модели данных. Этот класс является производным от класса Microsoft.EntityFrameworkCore.DbContext.
- Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Назовите класс TodoContext и нажмите Добавить.
Введите следующий код:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
Регистрация контекста базы данных
В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей. Контейнер предоставляет службу контроллерам.
Обновите Program.cs
следующий выделенный код:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Предыдущий код:
- Добавляет
using
директивы. - Добавляет контекст базы данных в контейнер внедрения зависимостей.
- Указывает, что контекст базы данных будет использовать базу данных в памяти.
Формирование шаблонов контроллера
Щелкните правой кнопкой мыши папку
Controllers
.Выберите Добавить>New Scaffolded Item.
Выберите Контроллер API с действиями, использующий Entity Framework, а затем выберите Добавить.
В диалоговом окне Контроллер API с действиями, использующий Entity Framework сделайте следующее:
- Выберите TodoItem (TodoApi.Models) в поле Класс модели.
- Выберите TodoContext (TodoApi.Models) в поле Класс контекста данных.
- Выберите Добавить.
Если операция формирования шаблонов завершается неудачно, нажмите кнопку Добавить, чтобы попытаться сформировать шаблон еще раз.
Сформированный код:
- Пометьте этот класс атрибутом
[ApiController]
. Этот атрибут указывает, что контроллер отвечает на запросы веб-API. Дополнительные сведения о поведении, которое реализует этот атрибут, см. в статье Создание веб-API с помощью ASP.NET Core. - Использует внедрение зависимостей для внедрения контекста базы данных (
TodoContext
) в контроллер. Контекст базы данных используется в каждом методе создания, чтения, обновления и удаления в контроллере.
Шаблоны ASP.NET Core для:
- Контроллеры с представлениями включают
[action]
в шаблоне маршрута. - Контроллеры API не включают
[action]
в шаблоне маршрута.
[action]
Если маркер не входит в шаблон маршрута, имя действия (имя метода) не входит в конечную точку. То есть имя связанного метода действия не используется в соответствующем маршруте.
Обновление метода создания PostTodoItem
Измените инструкцию возврата в PostTodoItem
и используйте оператор nameof:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST
, как указано атрибутом [HttpPost]
. Метод получает значение TodoItem
из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201.
HTTP 201
— это стандартныйHTTP POST
ответ для метода, создающего новый ресурс на сервере. - Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс". - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Тестирование PostTodoItem
Нажмите клавиши CTRL+F5, чтобы запустить приложение.
В окне браузера Swagger выберите POST /api/TodoItems, а затем нажмите кнопку "Попробовать".
В окне ввода текста запроса обновите JSON. Например,
{ "name": "walk dog", "isComplete": true }
Нажмите кнопку Выполнить.
Тестирование URI заголовка расположения
В предыдущем post пользовательский интерфейс Swagger отображает заголовок расположения в заголовках ответа. Например, location: https://localhost:7260/api/TodoItems/1
. Заголовок расположения отображает универсальный код ресурса (URI) для созданного ресурса.
Чтобы проверить заголовок расположения, выполните следующие действия.
В окне браузера Swagger выберите GET /api/TodoItems/{id}, а затем нажмите кнопку "Попробовать".
Введите
1
вid
поле ввода и нажмите кнопку "Выполнить".
Знакомство с методами GET
Реализуются две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
В предыдущем разделе показан пример /api/todoitems/{id}
маршрута.
Следуйте инструкциям POST, чтобы добавить другой элемент todo, а затем протестировать /api/todoitems
маршрут с помощью Swagger.
Это приложение использует выполняющуюся в памяти базу данных. Если приложение остановлено и запущено, предыдущий запрос GET не возвращает никаких данных. Если данные не возвращаются, данные для приложения получаются методом POST.
Маршрутизация и пути URL
Атрибут [HttpGet]
обозначает метод, который отвечает на HTTP GET
запрос. Путь URL для каждого метода формируется следующим образом:
Возьмите строку шаблона в атрибуте
Route
контроллера:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
Замените
[controller]
именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller"). В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.Если атрибут
[HttpGet]
имеет шаблон маршрута (например,[HttpGet("products")]
), добавьте его к пути. В этом примере шаблон не используется. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
В следующем методе GetTodoItem
"{id}"
— это переменная-заполнитель для уникального идентификатора элемента задачи. При вызове GetTodoItem
параметру метода id
присваивается значение "{id}"
в URL-адресе.
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
Возвращаемые значения
Тип возвращаемого значения для методов GetTodoItems
и GetTodoItem
— ActionResult<T>. ASP.NET Core автоматически сериализует объект в формат JSON и записывает данные JSON в тело сообщения ответа. Код ответа для этого типа возвращаемого значения равен 200 OK, что свидетельствует об отсутствии необработанных исключений. Необработанные исключения преобразуются в ошибки 5xx.
Типы возвращаемых значений ActionResult
могут представлять широкий спектр кодов состояний HTTP. Например, метод GetTodoItem
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404 NotFound.
- В противном случае метод возвращает код 200 с телом ответа JSON.
item
Возвращает результаты в ответеHTTP 200
.
Метод PutTodoItem
Изучите метод PutTodoItem
:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
аналогичен PostTodoItem
, за исключением того, что он использует HTTP PUT
. Ответ — 204 (Нет содержимого). Согласно спецификации HTTP, PUT
запрос требует от клиента отправки всей обновленной сущности, а не только изменений. Чтобы обеспечить поддержку частичных обновлений, используйте HTTP PATCH.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Используя пользовательский интерфейс Swagger, нажмите кнопку PUT для обновления TodoItem
идентификатора = 1 и задайте для него имя "feed fish"
. Обратите внимание, что ответ равен HTTP 204 No Content
.
Метод DeleteTodoItem
Изучите метод DeleteTodoItem
:
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
Тестирование метода DeleteTodoItem
Используйте пользовательский интерфейс Swagger для удаления TodoItem
идентификатора = 1. Обратите внимание, что ответ равен HTTP 204 No Content
.
Тестирование с помощью других средств
Существует множество других средств, которые можно использовать для тестирования веб-API, например:
- Обозреватель конечных точек Visual Studio и HTTP-файлы
- http-repl
- curl. Swagger использует
curl
и отображаетcurl
команды, которые он отправляет. - Fiddler
Дополнительные сведения см. в разделе:
- Минимальное руководство по API: тестирование с помощью HTTP-файлов и обозревателя конечных точек
- Установка и тестирование API с помощью
http-repl
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект TodoItem
. Рабочие приложения обычно ограничивают вводимые данные и возвращают их с помощью подмножества модели. Такое поведение реализовано по нескольким причинам, но в основном из соображений безопасности. Подмножество модели обычно называется объектом передачи данных (DTO), моделью ввода или моделью представления. В рамках этого руководства используется DTO.
DTO можно использовать для следующего:
- Предотвращение избыточной публикации.
- Скрытие свойств, которые не предназначены для просмотра клиентами.
- Пропуск некоторых свойств, чтобы уменьшить размер полезной нагрузки.
- Сведение графов объектов, содержащих вложенные объекты. Сведенные графы объектов могут быть удобнее для клиентов.
Чтобы продемонстрировать подход с применением DTO, обновите класс TodoItem
, включив в него поле секрета:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
Поле секрета должно быть скрыто в этом приложении, однако административное приложение может отобразить его.
Убедитесь, что вы можете отправить и получить секретное поле.
Создайте модель DTO:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Обновите TodoItemsController
для использования TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
Убедитесь, что вы можете отправить или получить секретное поле.
Вызов веб-API с помощью JavaScript
См . руководство. Вызов веб-API ASP.NET Core с помощью JavaScript.
Серия видео веб-API
См . видео: серия начинающих: веб-API.
Надежные шаблоны веб-приложений
См. статью "Шаблон надежных веб-приложений" for.NET видео и статьи YouTube по созданию современного, надежного, производительного, тестового, экономичного и масштабируемого приложения ASP.NET Core, будь то с нуля или рефакторинг существующего приложения.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Внимание
Компания Duende Software может потребовать лицензионный сбор за использование Duende IdentityServer в рабочей среде. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Публикация в Azure
Сведения о развертывании в Azure см. в разделе Краткое руководство. Развертывание веб-приложения ASP.NET.
Дополнительные ресурсы
Просмотреть или скачать пример кода для этого учебника. См. раздел Практическое руководство. Скачивание файла.
Дополнительные сведения см. на следующих ресурсах:
- Создание веб-API с помощью ASP.NET Core
- Руководство. Создание минимального API с помощью ASP.NET Core
- документация по веб-API ASP.NET Core с помощью Swagger / OpenAPI
- Использование Razor Pages с Entity Framework Core в ASP.NET Core: руководство 1 из 8
- Маршрутизация на действия контроллера в ASP.NET Core
- Типы возвращаемых действий контроллера в веб-API ASP.NET Core
- Развертывание приложений ASP.NET Core в Службе приложений Azure
- Размещение и развертывание ASP.NET Core
- Создание веб-API с помощью ASP.NET Core
В этом руководстве описаны основы создания веб-API на основе контроллера, использующего базу данных. Еще одним подходом к созданию API в ASP.NET Core является создание минимальных API. Сведения о выборе между минимальными API и API на основе контроллера см. в обзоре API. Руководство по созданию минимального API см . в руководстве по созданию минимального API с помощью ASP.NET Core.
Обзор
В этом руководстве создается следующий API-интерфейс:
API | Description | Текст запроса | Текст ответа |
---|---|---|---|
GET /api/todoitems |
Получение всех элементов задач | нет | Массив элементов задач |
GET /api/todoitems/{id} |
Получение объекта по идентификатору | нет | Элемент задачи |
POST /api/todoitems |
Добавление нового элемента | Элемент задачи | Элемент задачи |
PUT /api/todoitems/{id} |
Обновление существующего элемента | Элемент задачи | нет |
DELETE /api/todoitems/{id} |
Удаление элемента | нет | нет |
На следующем рисунке показана структура приложения.
Необходимые компоненты
Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- В поле поиска введите Веб-API.
- Выберите шаблон Веб-API ASP.NET Core и нажмите кнопку Далее.
- В диалоговом окне Настроить новый проект присвойте проекту имя TodoApi и нажмите кнопку Далее.
- В диалоговом окне "Дополнительные сведения":
- Убедитесь, что платформа — .NET 8.0 (долгосрочная поддержка).
- Убедитесь, что флажок Use controllers (uncheck to use minimal APIs) (Использовать контроллеры (снимите этот флажок для использования минимальных API)) установлен.
- Убедитесь, что установлен флажок для включения поддержки OpenAPI.
- Нажмите кнопку создания.
Добавление пакета NuGet
Пакет NuGet необходимо добавить для поддержки базы данных, используемой в этом руководстве.
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Откройте вкладку Browse (Обзор).
- Введите Microsoft.EntityFrameworkCore.InMemory в поле поиска и щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Тестирование проекта
Шаблон проекта создает API WeatherForecast
с поддержкой Swagger.
Нажмите клавиши CTRL+F5, чтобы выполнить запуск без отладчика.
Visual Studio отображает следующее диалоговое окно, если проект еще не настроен для использования SSL:
Выберите Да, чтобы сделать SSL-сертификат IIS Express доверенным.
Отобразится следующее диалоговое окно.
Выберите Да, если согласны доверять сертификату разработки.
Сведения о доверии к браузеру Firefox см. в разделе Ошибка сертификата браузера Firefox SEC_ERROR_INADEQUATE_KEY_USAGE.
Visual Studio запускает браузер по умолчанию и переходит https://localhost:<port>/swagger/index.html
в папку, где <port>
выбран случайный номер порта при создании проекта.
Откроется страница Swagger /swagger/index.html
. Выберите Get (Получить)>Try it out (Попробовать)>Execute (Выполнить). На странице отобразятся:
- команда Curl для тестирования API WeatherForecast;
- URL-адрес для тестирования API WeatherForecast;
- код, текст и заголовки ответа;
- Раскрывающийся список с типами носителей и примером значения и схемы.
Если страница Swagger не отображается, см. эту проблему на сайте GitHub.
Swagger используется для создания полезной документации и страниц справки для веб-API. В этом руководстве используется Swagger для тестирования приложения. Дополнительные сведения о Swagger см. в статье Документация по веб-API ASP.NET Core с использованием Swagger (OpenAPI).
Скопируйте и вставьте URL-адрес запроса в адресную строку браузера: https://localhost:<port>/weatherforecast
Возвращаемые данные JSON будут примерно такими:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
Добавление класса модели
Модель — это набор классов, представляющих данные, которыми управляет приложение. Для этого приложения используется класс модели TodoItem
.
- В обозревателе решений щелкните проект правой кнопкой мыши. Выберите Добавить>Новая папка. Назовите папку
Models
. - Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Присвойте классу имя TodoItem и выберите Добавить. - Замените код шаблона следующим кодом:
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Свойство Id
выступает в качестве уникального ключа реляционной базы данных.
Классы моделей можно размещать в любом месте проекта, но обычно для этого используется папка Models
.
Добавление контекста базы данных
Контекст базы данных —это основной класс, который координирует функциональные возможности Entity Framework для модели данных. Этот класс является производным от класса Microsoft.EntityFrameworkCore.DbContext.
- Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Назовите класс TodoContext и нажмите Добавить.
Введите следующий код:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
Регистрация контекста базы данных
В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей. Контейнер предоставляет службу контроллерам.
Обновите Program.cs
следующий выделенный код:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Предыдущий код:
- Добавляет
using
директивы. - Добавляет контекст базы данных в контейнер внедрения зависимостей.
- Указывает, что контекст базы данных будет использовать базу данных в памяти.
Формирование шаблонов контроллера
Щелкните правой кнопкой мыши папку
Controllers
.Выберите Добавить>New Scaffolded Item.
Выберите Контроллер API с действиями, использующий Entity Framework, а затем выберите Добавить.
В диалоговом окне Контроллер API с действиями, использующий Entity Framework сделайте следующее:
- Выберите TodoItem (TodoApi.Models) в поле Класс модели.
- Выберите TodoContext (TodoApi.Models) в поле Класс контекста данных.
- Выберите Добавить.
Если операция формирования шаблонов завершается неудачно, нажмите кнопку Добавить, чтобы попытаться сформировать шаблон еще раз.
Сформированный код:
- Пометьте этот класс атрибутом
[ApiController]
. Этот атрибут указывает, что контроллер отвечает на запросы веб-API. Дополнительные сведения о поведении, которое реализует этот атрибут, см. в статье Создание веб-API с помощью ASP.NET Core. - Использует внедрение зависимостей для внедрения контекста базы данных (
TodoContext
) в контроллер. Контекст базы данных используется в каждом методе создания, чтения, обновления и удаления в контроллере.
Шаблоны ASP.NET Core для:
- Контроллеры с представлениями включают
[action]
в шаблоне маршрута. - Контроллеры API не включают
[action]
в шаблоне маршрута.
[action]
Если маркер не входит в шаблон маршрута, имя действия (имя метода) не входит в конечную точку. То есть имя связанного метода действия не используется в соответствующем маршруте.
Обновление метода создания PostTodoItem
Измените инструкцию возврата в PostTodoItem
и используйте оператор nameof:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST
, как указано атрибутом [HttpPost]
. Метод получает значение TodoItem
из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201.
HTTP 201
— это стандартныйHTTP POST
ответ для метода, создающего новый ресурс на сервере. - Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс". - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Тестирование PostTodoItem
Нажмите клавиши CTRL+F5, чтобы запустить приложение.
В окне браузера Swagger выберите POST /api/TodoItems, а затем нажмите кнопку "Попробовать".
В окне ввода текста запроса обновите JSON. Например,
{ "name": "walk dog", "isComplete": true }
Нажмите кнопку Выполнить.
Тестирование URI заголовка расположения
В предыдущем post пользовательский интерфейс Swagger отображает заголовок расположения в заголовках ответа. Например, location: https://localhost:7260/api/TodoItems/1
. Заголовок расположения отображает универсальный код ресурса (URI) для созданного ресурса.
Чтобы проверить заголовок расположения, выполните следующие действия.
В окне браузера Swagger выберите GET /api/TodoItems/{id}, а затем нажмите кнопку "Попробовать".
Введите
1
вid
поле ввода и нажмите кнопку "Выполнить".
Знакомство с методами GET
Реализуются две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
В предыдущем разделе показан пример /api/todoitems/{id}
маршрута.
Следуйте инструкциям POST, чтобы добавить другой элемент todo, а затем протестировать /api/todoitems
маршрут с помощью Swagger.
Это приложение использует выполняющуюся в памяти базу данных. Если приложение остановлено и запущено, предыдущий запрос GET не возвращает никаких данных. Если данные не возвращаются, данные для приложения получаются методом POST.
Маршрутизация и пути URL
Атрибут [HttpGet]
обозначает метод, который отвечает на HTTP GET
запрос. Путь URL для каждого метода формируется следующим образом:
Возьмите строку шаблона в атрибуте
Route
контроллера:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
Замените
[controller]
именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller"). В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.Если атрибут
[HttpGet]
имеет шаблон маршрута (например,[HttpGet("products")]
), добавьте его к пути. В этом примере шаблон не используется. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
В следующем методе GetTodoItem
"{id}"
— это переменная-заполнитель для уникального идентификатора элемента задачи. При вызове GetTodoItem
параметру метода id
присваивается значение "{id}"
в URL-адресе.
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
Возвращаемые значения
Тип возвращаемого значения для методов GetTodoItems
и GetTodoItem
— ActionResult<T>. ASP.NET Core автоматически сериализует объект в формат JSON и записывает данные JSON в тело сообщения ответа. Код ответа для этого типа возвращаемого значения равен 200 OK, что свидетельствует об отсутствии необработанных исключений. Необработанные исключения преобразуются в ошибки 5xx.
Типы возвращаемых значений ActionResult
могут представлять широкий спектр кодов состояний HTTP. Например, метод GetTodoItem
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404 NotFound.
- В противном случае метод возвращает код 200 с телом ответа JSON.
item
Возвращает результаты в ответеHTTP 200
.
Метод PutTodoItem
Изучите метод PutTodoItem
:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
аналогичен PostTodoItem
, за исключением того, что он использует HTTP PUT
. Ответ — 204 (Нет содержимого). Согласно спецификации HTTP, PUT
запрос требует от клиента отправки всей обновленной сущности, а не только изменений. Чтобы обеспечить поддержку частичных обновлений, используйте HTTP PATCH.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Используя пользовательский интерфейс Swagger, нажмите кнопку PUT для обновления TodoItem
идентификатора = 1 и задайте для него имя "feed fish"
. Обратите внимание, что ответ равен HTTP 204 No Content
.
Метод DeleteTodoItem
Изучите метод DeleteTodoItem
:
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
Тестирование метода DeleteTodoItem
Используйте пользовательский интерфейс Swagger для удаления TodoItem
идентификатора = 1. Обратите внимание, что ответ равен HTTP 204 No Content
.
Тестирование с помощью других средств
Существует множество других средств, которые можно использовать для тестирования веб-API, например:
- Обозреватель конечных точек Visual Studio и HTTP-файлы
- http-repl
- curl. Swagger использует
curl
и отображаетcurl
команды, которые он отправляет. - Fiddler
Дополнительные сведения см. в разделе:
- Минимальное руководство по API: тестирование с помощью HTTP-файлов и обозревателя конечных точек
- Установка и тестирование API с помощью
http-repl
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект TodoItem
. Рабочие приложения обычно ограничивают вводимые данные и возвращают их с помощью подмножества модели. Такое поведение реализовано по нескольким причинам, но в основном из соображений безопасности. Подмножество модели обычно называется объектом передачи данных (DTO), моделью ввода или моделью представления. В рамках этого руководства используется DTO.
DTO можно использовать для следующего:
- Предотвращение избыточной публикации.
- Скрытие свойств, которые не предназначены для просмотра клиентами.
- Пропуск некоторых свойств, чтобы уменьшить размер полезной нагрузки.
- Сведение графов объектов, содержащих вложенные объекты. Сведенные графы объектов могут быть удобнее для клиентов.
Чтобы продемонстрировать подход с применением DTO, обновите класс TodoItem
, включив в него поле секрета:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
Поле секрета должно быть скрыто в этом приложении, однако административное приложение может отобразить его.
Убедитесь, что вы можете отправить и получить секретное поле.
Создайте модель DTO:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Обновите TodoItemsController
для использования TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
Убедитесь, что вы можете отправить или получить секретное поле.
Вызов веб-API с помощью JavaScript
См . руководство. Вызов веб-API ASP.NET Core с помощью JavaScript.
Серия видео веб-API
См . видео: серия начинающих: веб-API.
Надежные шаблоны веб-приложений
См. статью "Шаблон надежных веб-приложений" for.NET видео и статьи YouTube по созданию современного, надежного, производительного, тестового, экономичного и масштабируемого приложения ASP.NET Core, будь то с нуля или рефакторинг существующего приложения.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Внимание
Компания Duende Software может потребовать лицензионный сбор за использование Duende IdentityServer в рабочей среде. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Публикация в Azure
Сведения о развертывании в Azure см. в разделе Краткое руководство. Развертывание веб-приложения ASP.NET.
Дополнительные ресурсы
Просмотреть или скачать пример кода для этого учебника. См. раздел Практическое руководство. Скачивание файла.
Дополнительные сведения см. на следующих ресурсах:
- Создание веб-API с помощью ASP.NET Core
- Руководство. Создание минимального API с помощью ASP.NET Core
- документация по веб-API ASP.NET Core с помощью Swagger / OpenAPI
- Использование Razor Pages с Entity Framework Core в ASP.NET Core: руководство 1 из 8
- Маршрутизация на действия контроллера в ASP.NET Core
- Типы возвращаемых действий контроллера в веб-API ASP.NET Core
- Развертывание приложений ASP.NET Core в Службе приложений Azure
- Размещение и развертывание ASP.NET Core
- Создание веб-API с помощью ASP.NET Core
В этом руководстве описаны основы создания веб-API на основе контроллера, использующего базу данных. Еще одним подходом к созданию API в ASP.NET Core является создание минимальных API. Сведения о выборе между минимальными API и API на основе контроллера см. в обзоре API. Руководство по созданию минимального API см . в руководстве по созданию минимального API с помощью ASP.NET Core.
Обзор
В этом руководстве создается следующий API-интерфейс:
API | Description | Текст запроса | Текст ответа |
---|---|---|---|
GET /api/todoitems |
Получение всех элементов задач | нет | Массив элементов задач |
GET /api/todoitems/{id} |
Получение объекта по идентификатору | нет | Элемент задачи |
POST /api/todoitems |
Добавление нового элемента | Элемент задачи | Элемент задачи |
PUT /api/todoitems/{id} |
Обновление существующего элемента | Элемент задачи | нет |
DELETE /api/todoitems/{id} |
Удаление элемента | нет | нет |
На следующем рисунке показана структура приложения.
Необходимые компоненты
Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- В поле поиска введите Веб-API.
- Выберите шаблон Веб-API ASP.NET Core и нажмите кнопку Далее.
- В диалоговом окне Настроить новый проект присвойте проекту имя TodoApi и нажмите кнопку Далее.
- В диалоговом окне "Дополнительные сведения":
- Убедитесь, что платформа — .NET 8.0 (долгосрочная поддержка).
- Убедитесь, что флажок Use controllers (uncheck to use minimal APIs) (Использовать контроллеры (снимите этот флажок для использования минимальных API)) установлен.
- Убедитесь, что установлен флажок для включения поддержки OpenAPI.
- Нажмите кнопку создания.
Добавление пакета NuGet
Пакет NuGet необходимо добавить для поддержки базы данных, используемой в этом руководстве.
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Откройте вкладку Browse (Обзор).
- Введите Microsoft.EntityFrameworkCore.InMemory в поле поиска и щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Тестирование проекта
Шаблон проекта создает API WeatherForecast
с поддержкой Swagger.
Нажмите клавиши CTRL+F5, чтобы выполнить запуск без отладчика.
Visual Studio отображает следующее диалоговое окно, если проект еще не настроен для использования SSL:
Выберите Да, чтобы сделать SSL-сертификат IIS Express доверенным.
Отобразится следующее диалоговое окно.
Выберите Да, если согласны доверять сертификату разработки.
Сведения о доверии к браузеру Firefox см. в разделе Ошибка сертификата браузера Firefox SEC_ERROR_INADEQUATE_KEY_USAGE.
Visual Studio запускает браузер по умолчанию и переходит https://localhost:<port>/swagger/index.html
в папку, где <port>
выбран случайный номер порта при создании проекта.
Откроется страница Swagger /swagger/index.html
. Выберите Get (Получить)>Try it out (Попробовать)>Execute (Выполнить). На странице отобразятся:
- команда Curl для тестирования API WeatherForecast;
- URL-адрес для тестирования API WeatherForecast;
- код, текст и заголовки ответа;
- Раскрывающийся список с типами носителей и примером значения и схемы.
Если страница Swagger не отображается, см. эту проблему на сайте GitHub.
Swagger используется для создания полезной документации и страниц справки для веб-API. В этом руководстве используется Swagger для тестирования приложения. Дополнительные сведения о Swagger см. в статье Документация по веб-API ASP.NET Core с использованием Swagger (OpenAPI).
Скопируйте и вставьте URL-адрес запроса в адресную строку браузера: https://localhost:<port>/weatherforecast
Возвращаемые данные JSON будут примерно такими:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
Добавление класса модели
Модель — это набор классов, представляющих данные, которыми управляет приложение. Для этого приложения используется класс модели TodoItem
.
- В обозревателе решений щелкните проект правой кнопкой мыши. Выберите Добавить>Новая папка. Назовите папку
Models
. - Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Присвойте классу имя TodoItem и выберите Добавить. - Замените код шаблона следующим кодом:
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Свойство Id
выступает в качестве уникального ключа реляционной базы данных.
Классы моделей можно размещать в любом месте проекта, но обычно для этого используется папка Models
.
Добавление контекста базы данных
Контекст базы данных —это основной класс, который координирует функциональные возможности Entity Framework для модели данных. Этот класс является производным от класса Microsoft.EntityFrameworkCore.DbContext.
- Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Назовите класс TodoContext и нажмите Добавить.
Введите следующий код:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
Регистрация контекста базы данных
В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей. Контейнер предоставляет службу контроллерам.
Обновите Program.cs
следующий выделенный код:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Предыдущий код:
- Добавляет
using
директивы. - Добавляет контекст базы данных в контейнер внедрения зависимостей.
- Указывает, что контекст базы данных будет использовать базу данных в памяти.
Формирование шаблонов контроллера
Щелкните правой кнопкой мыши папку
Controllers
.Выберите Добавить>New Scaffolded Item.
Выберите Контроллер API с действиями, использующий Entity Framework, а затем выберите Добавить.
В диалоговом окне Контроллер API с действиями, использующий Entity Framework сделайте следующее:
- Выберите TodoItem (TodoApi.Models) в поле Класс модели.
- Выберите TodoContext (TodoApi.Models) в поле Класс контекста данных.
- Выберите Добавить.
Если операция формирования шаблонов завершается неудачно, нажмите кнопку Добавить, чтобы попытаться сформировать шаблон еще раз.
Сформированный код:
- Пометьте этот класс атрибутом
[ApiController]
. Этот атрибут указывает, что контроллер отвечает на запросы веб-API. Дополнительные сведения о поведении, которое реализует этот атрибут, см. в статье Создание веб-API с помощью ASP.NET Core. - Использует внедрение зависимостей для внедрения контекста базы данных (
TodoContext
) в контроллер. Контекст базы данных используется в каждом методе создания, чтения, обновления и удаления в контроллере.
Шаблоны ASP.NET Core для:
- Контроллеры с представлениями включают
[action]
в шаблоне маршрута. - Контроллеры API не включают
[action]
в шаблоне маршрута.
[action]
Если маркер не входит в шаблон маршрута, имя действия (имя метода) не входит в конечную точку. То есть имя связанного метода действия не используется в соответствующем маршруте.
Обновление метода создания PostTodoItem
Измените инструкцию возврата в PostTodoItem
и используйте оператор nameof:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST
, как указано атрибутом [HttpPost]
. Метод получает значение TodoItem
из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201.
HTTP 201
— это стандартныйHTTP POST
ответ для метода, создающего новый ресурс на сервере. - Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс". - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Тестирование PostTodoItem
Нажмите клавиши CTRL+F5, чтобы запустить приложение.
В окне браузера Swagger выберите POST /api/TodoItems, а затем нажмите кнопку "Попробовать".
В окне ввода текста запроса обновите JSON. Например,
{ "name": "walk dog", "isComplete": true }
Нажмите кнопку Выполнить.
Тестирование URI заголовка расположения
В предыдущем post пользовательский интерфейс Swagger отображает заголовок расположения в заголовках ответа. Например, location: https://localhost:7260/api/TodoItems/1
. Заголовок расположения отображает универсальный код ресурса (URI) для созданного ресурса.
Чтобы проверить заголовок расположения, выполните следующие действия.
В окне браузера Swagger выберите GET /api/TodoItems/{id}, а затем нажмите кнопку "Попробовать".
Введите
1
вid
поле ввода и нажмите кнопку "Выполнить".
Знакомство с методами GET
Реализуются две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
В предыдущем разделе показан пример /api/todoitems/{id}
маршрута.
Следуйте инструкциям POST, чтобы добавить другой элемент todo, а затем протестировать /api/todoitems
маршрут с помощью Swagger.
Это приложение использует выполняющуюся в памяти базу данных. Если приложение остановлено и запущено, предыдущий запрос GET не возвращает никаких данных. Если данные не возвращаются, данные для приложения получаются методом POST.
Маршрутизация и пути URL
Атрибут [HttpGet]
обозначает метод, который отвечает на HTTP GET
запрос. Путь URL для каждого метода формируется следующим образом:
Возьмите строку шаблона в атрибуте
Route
контроллера:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
Замените
[controller]
именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller"). В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.Если атрибут
[HttpGet]
имеет шаблон маршрута (например,[HttpGet("products")]
), добавьте его к пути. В этом примере шаблон не используется. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
В следующем методе GetTodoItem
"{id}"
— это переменная-заполнитель для уникального идентификатора элемента задачи. При вызове GetTodoItem
параметру метода id
присваивается значение "{id}"
в URL-адресе.
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
Возвращаемые значения
Тип возвращаемого значения для методов GetTodoItems
и GetTodoItem
— ActionResult<T>. ASP.NET Core автоматически сериализует объект в формат JSON и записывает данные JSON в тело сообщения ответа. Код ответа для этого типа возвращаемого значения равен 200 OK, что свидетельствует об отсутствии необработанных исключений. Необработанные исключения преобразуются в ошибки 5xx.
Типы возвращаемых значений ActionResult
могут представлять широкий спектр кодов состояний HTTP. Например, метод GetTodoItem
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404 NotFound.
- В противном случае метод возвращает код 200 с телом ответа JSON.
item
Возвращает результаты в ответеHTTP 200
.
Метод PutTodoItem
Изучите метод PutTodoItem
:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
аналогичен PostTodoItem
, за исключением того, что он использует HTTP PUT
. Ответ — 204 (Нет содержимого). Согласно спецификации HTTP, PUT
запрос требует от клиента отправки всей обновленной сущности, а не только изменений. Чтобы обеспечить поддержку частичных обновлений, используйте HTTP PATCH.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Используя пользовательский интерфейс Swagger, нажмите кнопку PUT для обновления TodoItem
идентификатора = 1 и задайте для него имя "feed fish"
. Обратите внимание, что ответ равен HTTP 204 No Content
.
Метод DeleteTodoItem
Изучите метод DeleteTodoItem
:
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
Тестирование метода DeleteTodoItem
Используйте пользовательский интерфейс Swagger для удаления TodoItem
идентификатора = 1. Обратите внимание, что ответ равен HTTP 204 No Content
.
Тестирование с помощью других средств
Существует множество других средств, которые можно использовать для тестирования веб-API, например:
- Обозреватель конечных точек Visual Studio и HTTP-файлы
- http-repl
- curl. Swagger использует
curl
и отображаетcurl
команды, которые он отправляет. - Fiddler
Дополнительные сведения см. в разделе:
- Минимальное руководство по API: тестирование с помощью HTTP-файлов и обозревателя конечных точек
- Установка и тестирование API с помощью
http-repl
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект TodoItem
. Рабочие приложения обычно ограничивают вводимые данные и возвращают их с помощью подмножества модели. Такое поведение реализовано по нескольким причинам, но в основном из соображений безопасности. Подмножество модели обычно называется объектом передачи данных (DTO), моделью ввода или моделью представления. В рамках этого руководства используется DTO.
DTO можно использовать для следующего:
- Предотвращение избыточной публикации.
- Скрытие свойств, которые не предназначены для просмотра клиентами.
- Пропуск некоторых свойств, чтобы уменьшить размер полезной нагрузки.
- Сведение графов объектов, содержащих вложенные объекты. Сведенные графы объектов могут быть удобнее для клиентов.
Чтобы продемонстрировать подход с применением DTO, обновите класс TodoItem
, включив в него поле секрета:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
Поле секрета должно быть скрыто в этом приложении, однако административное приложение может отобразить его.
Убедитесь, что вы можете отправить и получить секретное поле.
Создайте модель DTO:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Обновите TodoItemsController
для использования TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
Убедитесь, что вы можете отправить или получить секретное поле.
Вызов веб-API с помощью JavaScript
См . руководство. Вызов веб-API ASP.NET Core с помощью JavaScript.
Серия видео веб-API
См . видео: серия начинающих: веб-API.
Надежные шаблоны веб-приложений
См. статью "Шаблон надежных веб-приложений" for.NET видео и статьи YouTube по созданию современного, надежного, производительного, тестового, экономичного и масштабируемого приложения ASP.NET Core, будь то с нуля или рефакторинг существующего приложения.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Внимание
Компания Duende Software может потребовать лицензионный сбор за использование Duende IdentityServer в рабочей среде. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Публикация в Azure
Сведения о развертывании в Azure см. в разделе Краткое руководство. Развертывание веб-приложения ASP.NET.
Дополнительные ресурсы
Просмотреть или скачать пример кода для этого учебника. См. раздел Практическое руководство. Скачивание файла.
Дополнительные сведения см. на следующих ресурсах:
- Создание веб-API с помощью ASP.NET Core
- Руководство. Создание минимального API с помощью ASP.NET Core
- документация по веб-API ASP.NET Core с помощью Swagger / OpenAPI
- Использование Razor Pages с Entity Framework Core в ASP.NET Core: руководство 1 из 8
- Маршрутизация на действия контроллера в ASP.NET Core
- Типы возвращаемых действий контроллера в веб-API ASP.NET Core
- Развертывание приложений ASP.NET Core в Службе приложений Azure
- Размещение и развертывание ASP.NET Core
- Создание веб-API с помощью ASP.NET Core
ASP.NET Core