Руководство по созданию веб-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("PostTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(PostTodoItem), 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 "Создан ресурс". - Указывает действие
PostTodoItem
для создания 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
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404NotFound (Не найдено).
- В противном случае метод возвращает код 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 7.0 (или более поздняя версия).
- Убедитесь, что флажок Use controllers (uncheck to use minimal APIs) (Использовать контроллеры (снимите этот флажок для использования минимальных API)) установлен.
- Нажмите кнопку создания.
Примечание.
Рекомендации по добавлению пакетов в приложения .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. В этом учебнике рассматривается создание веб-API. Дополнительные сведения о 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.
Добавление пакетов NuGet
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Перейдите на вкладку Обзор и введите
Microsoft.EntityFrameworkCore.InMemory
в поле поиска. - В области слева щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Добавление контекста базы данных TodoContext
- Щелкните папку
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("PostTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(PostTodoItem), 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 "Создан ресурс". - Указывает действие
PostTodoItem
для создания 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
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404NotFound (Не найдено).
- В противном случае метод возвращает код 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
.
Тестирование с помощью http-repl, Postman или curl
http-repl, Postman и curl часто используются для тестирования API. Swagger использует curl
и отображает отправленную curl
команду.
Инструкции по этим средствам см. по следующим ссылкам:
Дополнительные сведения см http-repl
. в разделе "Тестовые веб-API" с помощью HttpRepl.
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект 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.
- Добавление класса модели и контекста базы данных.
- Формирование шаблонов контроллера с использованием методов CRUD.
- Настройка маршрутизации, URL-пути и возвращаемых значений.
- Вызов веб-API с помощью http-repl.
В итоге вы получите веб-API, позволяющий работать с элементами списка дел, хранимыми в базе данных.
Обзор
В этом руководстве создается следующий 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 и веб-разработка.
- Пакет SDK для .NET 6.0
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- В поле поиска введите Веб-API.
- Выберите шаблон Веб-API ASP.NET Core и нажмите кнопку Далее.
- В диалоговом окне Настроить новый проект присвойте проекту имя TodoApi и нажмите кнопку Далее.
- В диалоговом окне "Дополнительные сведения":
- Убедитесь, что для параметра Платформа выбрано значение .NET 6.0 (долгосрочная поддержка).
- Убедитесь, что флажок Use controllers (uncheck to use minimal APIs) (Использовать контроллеры (снимите этот флажок для использования минимальных API)) установлен.
- Нажмите кнопку создания.
Примечание.
Рекомендации по добавлению пакетов в приложения .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. В этом учебнике рассматривается создание веб-API. Дополнительные сведения о 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"
}
]
Обновление launchUrl
В файле Properties/launchSettings.json обновите launchUrl
с "swagger"
на "api/todoitems"
.
"launchUrl": "api/todoitems",
Поскольку Swagger будет удален, в предыдущей разметке был изменен URL-адрес, который запускается в методе GET контроллера, добавленного в следующих разделах.
Добавление класса модели
Модель — это набор классов, представляющих данные, которыми управляет приложение. Модель этого приложения содержит единственный класс 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.
Добавление пакетов NuGet
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Перейдите на вкладку Обзор и введите
Microsoft.EntityFrameworkCore.InMemory
в поле поиска. - В области слева щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Добавление контекста базы данных TodoContext
- Щелкните папку
Models
правой кнопкой мыши и выберите пункты Добавить>Класс. Назовите класс TodoContext и нажмите Добавить.
Введите следующий код:
using Microsoft.EntityFrameworkCore; using System.Diagnostics.CodeAnalysis; 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);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
//builder.Services.AddSwaggerGen(c =>
//{
// c.SwaggerDoc("v1", new() { Title = "TodoApi", Version = "v1" });
//});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (builder.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
//app.UseSwagger(); // UseSwaggerUI Protected by if (env.IsDevelopment())
//app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1"));
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Предыдущий код:
- Удаляет вызовы Swagger.
- Удаляет неиспользуемые директивы
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("PostTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(PostTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST, обозначенным атрибутом [HttpPost]
. Этот метод получает значение элемента списка дел из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201. HTTP 201 представляет собой стандартный ответ для метода HTTP POST, создающий ресурс на сервере.
- Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс". - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Установка http-repl
В рамках этого руководства для проверки веб-API используется средство http-repl.
Выполните в командной строке следующую команду:
dotnet tool install -g Microsoft.dotnet-httprepl
Примечание.
По умолчанию архитектура двоичных файлов .NET для установки представляет архитектуру операционной системы. Чтобы указать другую архитектуру ОС, см . параметр dotnet tool install, --arch. Дополнительные сведения см. в статье о проблеме GitHub dotnet/AspNetCore.Docs #29262.
Если у вас не установлены среда выполнения или пакет SDK для .NET 6.0, установите среду выполнения .NET 6.0.
Тестирование PostTodoItem
Нажмите клавиши CTRL+F5, чтобы запустить приложение.
Откройте новое окно терминала и выполните приведенные ниже команды. Если приложение использует другой номер порта, укажите его вместо 5001 в команде httprepl.
httprepl https://localhost:5001/api/todoitems post -h Content-Type=application/json -c "{"name":"walk dog","isComplete":true}"
Ниже показан пример результатов выполнения команды :
HTTP/1.1 201 Created Content-Type: application/json; charset=utf-8 Date: Tue, 07 Sep 2021 20:39:47 GMT Location: https://localhost:5001/api/TodoItems/1 Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "walk dog", "isComplete": true }
Тестирование URI заголовка расположения
Чтобы проверить заголовок location, скопируйте его и вставьте в команду httprepl get
.
В следующем примере предполагается, что вы все еще находитесь в сеансе httprepl. Если вы уже завершили сеанс httprepl, измените connect
на httprepl
в следующих командах:
connect https://localhost:5001/api/todoitems/1
get
Ниже показан пример результатов выполнения команды :
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 07 Sep 2021 20:48:10 GMT
Server: Kestrel
Transfer-Encoding: chunked
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
Знакомство с методами GET
Реализуются две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
Это был пример маршрута /api/todoitems/{id}
. Проверьте маршрут /api/todoitems
:
connect https://localhost:5001/api/todoitems
get
Ниже показан пример результатов выполнения команды :
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 07 Sep 2021 20:59:21 GMT
Server: Kestrel
Transfer-Encoding: chunked
[
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
]
На этот раз возвращается JSON с массивом из одного элемента.
Это приложение использует выполняющуюся в памяти базу данных. Если остановить и вновь запустить его, предшествующий запрос 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
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404NotFound (Не найдено).
- В противном случае метод возвращает код 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
произойдет ошибка, вызовите GET
, чтобы в базе данных существовал один элемент.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Обновите элемент списка дел с идентификатором 1 и присвойте ему имя "feed fish"
:
connect https://localhost:5001/api/todoitems/1
put -h Content-Type=application/json -c "{"id":1,"name":"feed fish","isComplete":true}"
Ниже показан пример результатов выполнения команды :
HTTP/1.1 204 No Content
Date: Tue, 07 Sep 2021 21:20:47 GMT
Server: Kestrel
Метод 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
Удалите элемент списка задач с идентификатором Id = 1:
connect https://localhost:5001/api/todoitems/1
delete
Ниже показан пример результатов выполнения команды :
HTTP/1.1 204 No Content
Date: Tue, 07 Sep 2021 21:43:00 GMT
Server: Kestrel
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект 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
[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);
}
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
{
if (id != todoItemDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoItemDTO.Name;
todoItem.IsComplete = todoItemDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> CreateTodoItem(TodoItemDTO todoItemDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// 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.
Добавление поддержки аутентификации в веб-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.
- Добавление класса модели и контекста базы данных.
- Формирование шаблонов контроллера с использованием методов CRUD.
- Настройка маршрутизации, URL-пути и возвращаемых значений.
- Вызов веб-API с помощью Postman.
В итоге вы получите веб-API, позволяющий работать с элементами списка дел, хранимыми в базе данных.
Обзор
В этом руководстве создается следующий API-интерфейс:
API | Description | Текст запроса | Текст ответа |
---|---|---|---|
GET /api/todoitems |
Получение всех элементов задач | нет | Массив элементов задач |
GET /api/todoitems/{id} |
Получение объекта по идентификатору | нет | Элемент задачи |
POST /api/todoitems |
Добавление нового элемента | Элемент задачи | Элемент задачи |
PUT /api/todoitems/{id} |
Обновление существующего элемента | Элемент задачи | нет |
DELETE /api/todoitems/{id} |
Удаление элемента | нет | нет |
На следующем рисунке показана структура приложения.
Необходимые компоненты
- Visual Studio 2019 16.8 или более поздней версии с рабочей нагрузкой ASP.NET и разработка веб-приложений
- Пакет SDK для .NET 5.0
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- Выберите шаблон Веб-API ASP.NET Core и нажмите кнопку Далее.
- Назовите проект TodoApi и нажмите Создать.
- Убедитесь, что в диалоговом окне Создание веб-приложения ASP.NET Core выбраны платформы .NET Core и ASP.NET Core 5.0. Выберите шаблон API и нажмите кнопку Создать.
Примечание.
Рекомендации по добавлению пакетов в приложения .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 запустит:
- веб-сервер IIS Express;
- браузер по умолчанию и перейдет к
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. В этом учебнике рассматривается создание веб-API. Дополнительные сведения о 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"
}
]
Обновление launchUrl
В файле Properties/launchSettings.json обновите launchUrl
с "swagger"
на "api/todoitems"
.
"launchUrl": "api/todoitems",
Поскольку Swagger будет удален, в предыдущей разметке был изменен URL-адрес, который запускается в методе GET контроллера, добавленного в следующих разделах.
Добавление класса модели
Модель — это набор классов, представляющих данные, которыми управляет приложение. Модель этого приложения содержит единственный класс 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.
Добавление пакетов NuGet
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Перейдите на вкладку Обзор и введите
Microsoft.EntityFrameworkCore.InMemory
в поле поиска. - В области слева щелкните
Microsoft.EntityFrameworkCore.InMemory
. - Установите флажок Проект в области справа и выберите Установить.
Добавление контекста базы данных TodoContext
- Щелкните папку
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; } } }
Регистрация контекста базы данных
В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей. Контейнер предоставляет службу контроллерам.
Обновите Startup.cs
, включив в него следующий код.
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
//services.AddSwaggerGen(c =>
//{
// c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoApi", Version = "v1" });
//});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
//app.UseSwagger(); // UseSwaggerUI Protected by if (env.IsDevelopment())
//app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Предыдущий код:
- Удаляет вызовы Swagger.
- Удалите неиспользуемые объявления
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:
// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
//return CreatedAtAction("PostTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(PostTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST, обозначенным атрибутом [HttpPost]
. Этот метод получает значение элемента списка дел из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201. HTTP 201 представляет собой стандартный ответ для метода HTTP POST, создающий ресурс на сервере.
- Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 201. - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Установка Postman
В этом учебнике для тестирования веб-API используется Postman.
- Установка Postman
- Запустите веб-приложение.
- Запустите Postman.
- Отключите проверку SSL-сертификата:
- Postman для Windows: выберите Файл>Параметры (вкладка Общие) и отключите параметр Проверка SSL-сертификата.
- Postman для macOS: выберите Postman>Settings (Параметры) (вкладка General (Общие)) и отключите параметр SSL certificate verification (Проверка SSL-сертификата).
Предупреждение
После тестирования контроллера снова включите проверку SSL-сертификата.
Тестирование PostTodoItem с использованием Postman
Создайте новый запрос.
Установите HTTP-метод
POST
.Задайте для URI значение
https://localhost:<port>/api/todoitems
. Например,https://localhost:5001/api/todoitems
.Выберите вкладку Body (Текст).
Установите переключатель без обработки.
Задайте тип JSON (приложение/json).
В теле запроса введите код JSON для элемента списка дел:
{ "name":"walk dog", "isComplete":true }
Выберите Отправить.
Тестирование URI заголовка расположения
URI заголовка расположения можно протестировать в браузере. Скопируйте и вставьте URI заголовка расположения в строку браузера.
Чтобы протестировать в Postman, выполните следующие действия.
Перейдите на вкладку Заголовки в области Ответ.
Скопируйте значение заголовка Расположение:
Установите HTTP-метод
GET
.Задайте для URI значение
https://localhost:<port>/api/todoitems/1
. Например,https://localhost:5001/api/todoitems/1
.Выберите Отправить.
Знакомство с методами GET
Реализуются две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
Протестируйте приложение, вызвав эти две конечные точки в браузере или в Postman. Например:
https://localhost:5001/api/todoitems
https://localhost:5001/api/todoitems/1
При вызове GetTodoItems
возвращается примерно такой ответ:
[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
Тестирование Get с использованием Postman
- Создайте новый запрос.
- Укажите метод HTTP GET.
- Задайте для URI запроса значение
https://localhost:<port>/api/todoitems
. Например,https://localhost:5001/api/todoitems
. - Выберите режим Представление с двумя областями в Postman.
- Выберите Отправить.
Это приложение использует выполняющуюся в памяти базу данных. Если остановить и вновь запустить его, предшествующий запрос GET не возвратит никаких данных. Если данные не возвращаются, данные для приложения получаются методом POST.
Маршрутизация и пути URL
Атрибут [HttpGet]
обозначает метод, который отвечает на запрос HTTP GET. Путь URL для каждого метода формируется следующим образом:
Возьмите строку шаблона в атрибуте
Route
контроллера:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }
Замените
[controller]
именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller"). В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.Если атрибут
[HttpGet]
имеет шаблон маршрута (например,[HttpGet("products")]
), добавьте его к пути. В этом примере шаблон не используется. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
В следующем методе GetTodoItem
"{id}"
— это переменная-заполнитель для уникального идентификатора элемента задачи. При вызове GetTodoItem
параметру метода id
присваивается значение "{id}"
в URL-адресе.
// GET: api/TodoItems/5
[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
может возвращать два разных значения состояния:
- Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает код ошибки 404NotFound (Не найдено).
- В противном случае метод возвращает код 200 с телом ответа в формате JSON. При возвращении
item
возвращается ответ HTTP 200.
Метод PutTodoItem
Изучите метод PutTodoItem
:
// PUT: api/TodoItems/5
[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
, вызовите GET
, чтобы в базе данных был один элемент.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Обновите элемент списка дел с идентификатором 1 и присвойте ему имя "feed fish"
:
{
"Id":1,
"name":"feed fish",
"isComplete":true
}
На следующем рисунке показан процесс обновления Postman:
Метод DeleteTodoItem
Изучите метод DeleteTodoItem
:
// 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();
}
Тестирование метода DeleteTodoItem
Удалите элемент списка дел с помощью Postman:
- Укажите метод
DELETE
. - Укажите URI удаляемого объекта (например,
https://localhost:5001/api/todoitems/1
). - Выберите Отправить.
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект 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:
public class TodoItemDTO
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
Обновите TodoItemsController
для использования TodoItemDTO
:
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
[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);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
{
if (id != todoItemDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoItemDTO.Name;
todoItem.IsComplete = todoItemDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> CreateTodoItem(TodoItemDTO todoItemDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
[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) =>
_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
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.
- Добавление класса модели и контекста базы данных.
- Формирование шаблонов контроллера с использованием методов CRUD.
- Настройка маршрутизации, URL-пути и возвращаемых значений.
- Вызов веб-API с помощью Postman.
В итоге вы получите веб-API, позволяющий работать с элементами списка дел, хранимыми в базе данных.
Обзор
В этом руководстве создается следующий API-интерфейс:
API | Description | Текст запроса | Текст ответа |
---|---|---|---|
GET /api/todoitems |
Получение всех элементов задач | нет | Массив элементов задач |
GET /api/todoitems/{id} |
Получение объекта по идентификатору | нет | Элемент задачи |
POST /api/todoitems |
Добавление нового элемента | Элемент задачи | Элемент задачи |
PUT /api/todoitems/{id} |
Обновление существующего элемента | Элемент задачи | нет |
DELETE /api/todoitems/{id} |
Удаление элемента | нет | нет |
На следующем рисунке показана структура приложения.
Необходимые компоненты
- Visual Studio 2019 16.4 или более поздней версии с рабочей нагрузкой ASP.NET и разработка веб-приложений
- Пакет SDK для .NET Core 3.1
Создание веб-проекта
- В меню Файл выберите пункт Создать>Проект.
- Выберите шаблон Веб-приложение ASP.NET Core и нажмите Далее.
- Назовите проект TodoApi и нажмите Создать.
- В диалоговом окне Создание веб-приложения ASP.NET Core убедитесь в том, что выбраны платформы .NET Core и ASP.NET Core 3.1. Выберите шаблон API и нажмите кнопку Создать.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Проверка API
Шаблон проекта создает API WeatherForecast
. Вызовите метод Get
из браузера для тестирования приложения.
Нажмите клавиши CTRL+F5, чтобы запустить приложение. Visual Studio запустит браузер и перейдет к https://localhost:<port>/weatherforecast
, где <port>
— это номер порта, выбранный случайным образом.
Если появится диалоговое окно с запросом о необходимости доверять сертификату IIS Express, выберите Да. В появляющемся следом диалоговом окне Предупреждение системы безопасности выберите Да.
Возвращаемые данные 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 и выберите Добавить.Замените код шаблона следующим кодом:
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
.
Добавление пакетов NuGet
- В меню Средства выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.
- Перейдите на вкладку Обзор и введите Microsoft.EntityFrameworkCore.InMemory в поле поиска.
- На панели слева выберите Microsoft.EntityFrameworkCore.InMemory.
- Установите флажок Проект в области справа и выберите Установить.
Добавление контекста базы данных TodoContext
- Щелкните папку
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; } } }
Регистрация контекста базы данных
В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей. Контейнер предоставляет службу контроллерам.
Обновите Startup.cs
следующий выделенный код:
// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Предыдущий код:
- Удалите неиспользуемые объявления
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:
// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
//return CreatedAtAction("PostTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(PostTodoItem), new { id = todoItem.Id }, todoItem);
}
Предыдущий код является методом HTTP POST, обозначенным атрибутом [HttpPost]
. Этот метод получает значение элемента списка дел из текста HTTP-запроса.
Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
Метод CreatedAtAction:
- В случае успеха возвращает код состояния HTTP 201. HTTP 201 представляет собой стандартный ответ для метода HTTP POST, создающий ресурс на сервере.
- Добавляет в ответ заголовок Location. Заголовок
Location
указывает URI новой созданной задачи. Дополнительные сведения см. в статье 201. - Указывает действие
GetTodoItem
для создания URI заголовкаLocation
. Ключевое словоnameof
C# используется для предотвращения жесткого программирования имени действия в вызовеCreatedAtAction
.
Установка Postman
В этом учебнике для тестирования веб-API используется Postman.
- Установка Postman
- Запустите веб-приложение.
- Запустите Postman.
- Отключите проверку SSL-сертификата:
- Postman для Windows: выберите Файл>Параметры (вкладка Общие) и отключите параметр Проверка SSL-сертификата.
- Postman для macOS: выберите Postman>Settings (Параметры) (вкладка General (Общие)) и отключите параметр SSL certificate verification (Проверка SSL-сертификата).
Предупреждение
После тестирования контроллера снова включите проверку SSL-сертификата.
Тестирование PostTodoItem с использованием Postman
Создайте новый запрос.
Установите HTTP-метод
POST
.Задайте для URI значение
https://localhost:<port>/api/todoitems
. Например,https://localhost:5001/api/todoitems
.Выберите вкладку Body (Текст).
Установите переключатель без обработки.
Задайте тип JSON (приложение/json).
В теле запроса введите код JSON для элемента списка дел:
{ "name":"walk dog", "isComplete":true }
Выберите Отправить.
Тестирование URI заголовка расположения с помощью Postman
Перейдите на вкладку Заголовки в области Ответ.
Скопируйте значение заголовка Расположение:
Установите HTTP-метод
GET
.Задайте для URI значение
https://localhost:<port>/api/todoitems/1
. Например,https://localhost:5001/api/todoitems/1
.Выберите Отправить.
Знакомство с методами GET
Эти методы реализуют две конечные точки GET:
GET /api/todoitems
GET /api/todoitems/{id}
Протестируйте приложение, вызвав эти две конечные точки в браузере или в Postman. Например:
https://localhost:5001/api/todoitems
https://localhost:5001/api/todoitems/1
При вызове GetTodoItems
возвращается примерно такой ответ:
[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
Тестирование Get с использованием Postman
- Создайте новый запрос.
- Укажите метод HTTP GET.
- Задайте для URI запроса значение
https://localhost:<port>/api/todoitems
. Например,https://localhost:5001/api/todoitems
. - Выберите режим Представление с двумя областями в Postman.
- Выберите Отправить.
Это приложение использует выполняющуюся в памяти базу данных. Если остановить и вновь запустить его, предшествующий запрос GET не возвратит никаких данных. Если данные не возвращаются, данные для приложения получаются методом POST.
Маршрутизация и пути URL
Атрибут [HttpGet]
обозначает метод, который отвечает на запрос HTTP GET. Путь URL для каждого метода формируется следующим образом:
Возьмите строку шаблона в атрибуте
Route
контроллера:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; }
Замените
[controller]
именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller"). В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.Если атрибут
[HttpGet]
имеет шаблон маршрута (например,[HttpGet("products")]
), добавьте его к пути. В этом примере шаблон не используется. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].
В следующем методе GetTodoItem
"{id}"
— это переменная-заполнитель для уникального идентификатора элемента задачи. При вызове GetTodoItem
параметру метода id
присваивается значение "{id}"
в URL-адресе.
// GET: api/TodoItems/5
[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, что свидетельствует об отсутствии необработанных исключений. Необработанные исключения преобразуются в ошибки 5xx.
Типы возвращаемых значений ActionResult
могут представлять широкий спектр кодов состояний HTTP. Например, метод GetTodoItem
может возвращать два разных значения состояния:
- Если элемент не совпадает с запрошенным идентификатором, метод возвращает код ошибки 404 NotFound .
- В противном случае метод возвращает код 200 с телом ответа в формате JSON. При возвращении
item
возвращается ответ HTTP 200.
Метод PutTodoItem
Изучите метод PutTodoItem
:
// PUT: api/TodoItems/5
[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
, вызовите GET
, чтобы в базе данных был один элемент.
Тестирование метода PutTodoItem
В этом примере используется база данных в памяти, которая должна быть инициирована при каждом запуске приложения. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.
Обновите элемент списка дел с идентификатором 1 и присвойте ему имя "feed fish":
{
"id":1,
"name":"feed fish",
"isComplete":true
}
На следующем рисунке показан процесс обновления Postman:
Метод DeleteTodoItem
Изучите метод DeleteTodoItem
:
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return todoItem;
}
Тестирование метода DeleteTodoItem
Удалите элемент списка дел с помощью Postman:
- Укажите метод
DELETE
. - Укажите URI удаляемого объекта (например,
https://localhost:5001/api/todoitems/1
). - Выберите Отправить.
Предотвращение избыточной публикации
В настоящее время пример приложения предоставляет весь объект TodoItem
. Рабочие приложения обычно ограничивают вводимые данные и возвращают их с помощью подмножества модели. Это связано с несколькими причинами, и безопасность является основной. Подмножество модели обычно называется объектом передачи данных (DTO), моделью ввода или моделью представления. В этой статье используется DTO.
DTO можно использовать для следующего:
- Предотвращение избыточной публикации.
- Скрытие свойств, которые не предназначены для просмотра клиентами.
- Пропуск некоторых свойств, чтобы уменьшить размер полезной нагрузки.
- Сведение графов объектов, содержащих вложенные объекты. Сведенные графы объектов могут быть удобнее для клиентов.
Чтобы продемонстрировать подход с применением DTO, обновите класс TodoItem
, включив в него поле секрета:
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
public string Secret { get; set; }
}
Поле секрета должно быть скрыто в этом приложении, однако административное приложение может отобразить его.
Убедитесь, что вы можете отправить и получить секретное поле.
Создайте модель DTO:
public class TodoItemDTO
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
Обновите TodoItemsController
для использования TodoItemDTO
:
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
[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);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
{
if (id != todoItemDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoItemDTO.Name;
todoItem.IsComplete = todoItemDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> CreateTodoItem(TodoItemDTO todoItemDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
[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) =>
_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
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
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по