Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
Это не последняя версия этой статьи. Для текущей версии см. версию .NET 9 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Для получения дополнительной информации см. Политику поддержки .NET и .NET Core. Для текущей версии см. версию .NET 9 этой статьи.
Это важно
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Корпорация Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых в отношении информации, предоставленной здесь.
Для текущей версии см. версию .NET 9 этой статьи.
Пратик Хандельвал и Скотт Адди
В этом руководстве создается веб-API, который выполняет операции создания, чтения, обновления и удаления (CRUD) в базе данных MongoDB NoSQL.
В этом руководстве вы узнаете, как:
- Настройка MongoDB
- Создание базы данных MongoDB
- Определение коллекции и схемы MongoDB
- Выполнение операций CRUD MongoDB из веб-API
- Настройка сериализации JSON
Предпосылки
Visual Studio 2022 с рабочей нагрузкой ASP.NET и разработка веб-приложений.
Настройка MongoDB
Включите доступ к MongoDB и оболочке MongoDB из любого места на машине разработки (Windows/Linux/macOS):
Скачайте и установите оболочку MongoDB:
- macOS/Linux: выберите каталог для извлечения оболочки MongoDB. Добавьте полученный путь к переменной среды
mongosh
PATH
. - Windows: Оболочка MongoDB (mongosh.exe) установлена в C:\Users\<user>\AppData\Local\Programs\mongosh. Добавьте полученный путь к переменной среды
mongosh.exe
PATH
.
- macOS/Linux: выберите каталог для извлечения оболочки MongoDB. Добавьте полученный путь к переменной среды
Скачайте и установите MongoDB:
- macOS/Linux: проверьте каталог, по которому был установлен MongoDB, обычно в /usr/local/mongodb. Добавьте полученный путь к переменной среды
mongodb
PATH
. - Windows: MongoDB устанавливается в C:\Program Files\MongoDB по умолчанию. Добавьте C:\Program Files\MongoDB\Server\<version_number>\bin в
PATH
переменную среды.
- macOS/Linux: проверьте каталог, по которому был установлен MongoDB, обычно в /usr/local/mongodb. Добавьте полученный путь к переменной среды
Выберите каталог хранилища данных: выберите каталог на компьютере разработки для хранения данных. Если такого каталога нет, создайте его. Оболочка MongoDB не создает новые каталоги:
- macOS/Linux: например,
/usr/local/var/mongodb
. - Windows: например,
C:\\BooksData
.
- macOS/Linux: например,
В командной оболочке ОС (а не в оболочке MongoDB) используйте следующую команду, чтобы подключиться к MongoDB через порт 27017 по умолчанию. Замените
<data_directory_path>
каталог, выбранный на предыдущем шаге.mongod --dbpath <data_directory_path>
Используйте ранее установленную оболочку MongoDB в следующих шагах для создания базы данных, создания коллекций и хранения документов. Дополнительные сведения о командах оболочки MongoDB см. в статье mongosh
.
Откройте экземпляр командной оболочки MongoDB, запуская
mongosh.exe
или выполнив следующую команду в командной оболочке:mongosh
В командной оболочке подключитесь к тестовой базе данных по умолчанию, выполнив следующую команду:
use BookStore
База данных с именем BookStore создается, если она еще не существует. Если база данных существует, его подключение открывается для транзакций.
Создайте коллекцию с помощью следующей
Books
команды:db.createCollection('Books')
Отображается следующий результат:
{ "ok" : 1 }
Определите схему для
Books
коллекции и вставьте два документа с помощью следующей команды:db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
Отображается результат, аналогичный следующему:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Замечание
Результаты
ObjectId
, показанные в предыдущем примере, не будут совпадать с результатами, показанными в командной оболочке.Просмотрите документы в базе данных с помощью следующей команды:
db.Books.find().pretty()
Отображается результат, аналогичный следующему:
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Схема добавляет автоматическое свойство
_id
типаObjectId
для каждого документа.
Создание проекта веб-API ASP.NET Core
- Перейдите к файлу>нового>проекта.
- Выберите тип проекта веб-API ASP.NET Core и нажмите кнопку "Далее".
- Назовите проект BookStoreApi и нажмите кнопку "Далее".
- В диалоговом окне Дополнительные сведения выполните следующие действия.
- Убедитесь, что фреймворк — это .NET 9.0 (Стандартная поддержка версии).
- Убедитесь, что установлен флажок " Использовать контроллеры ".
- Убедитесь, что установлен флажок для включения поддержки OpenAPI.
- Выберите Создать.
В окне консоли диспетчера пакетов перейдите в корневой каталог проекта. Выполните следующую команду, чтобы установить драйвер .NET для MongoDB:
Install-Package MongoDB.Driver
Добавление модели сущности
Добавьте каталог Models в корневой каталог проекта.
Book
Добавьте класс в каталог Models со следующим кодом:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
В предыдущем классе свойство
Id
выглядит следующим образом:- Требуется для сопоставления объекта CLR с коллекцией MongoDB.
- Отмечено с помощью
[BsonId]
, чтобы сделать это свойство основным ключом документа. - Аннотировано с
[BsonRepresentation(BsonType.ObjectId)]
, чтобы разрешить передачу параметра как типаstring
, вместо структуры ObjectId. Mongo обрабатывает преобразование изstring
вObjectId
.
Свойство
BookName
аннотировано атрибутом[BsonElement]
. Значение атрибутаName
представляет имя свойства в коллекции MongoDB.
Добавление модели конфигурации
Добавьте следующие значения конфигурации базы данных в
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
BookStoreDatabaseSettings
Добавьте класс в каталог Models со следующим кодом:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
BookStoreDatabaseSettings
Предыдущий класс используется для хранения значенийappsettings.json
свойств файлаBookStoreDatabase
. Имена свойств JSON и C# называются идентичными, чтобы упростить процесс сопоставления.Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
В приведенном выше коде экземпляр конфигурации, к которому привязан раздел файла
appsettings.json
, регистрируется в контейнере внедрения зависимостей (DI). Например, свойствоBookStoreDatabaseSettings
объектаConnectionString
заполняется свойствомBookStoreDatabase:ConnectionString
вappsettings.json
.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBookStoreDatabaseSettings
.using BookStoreApi.Models;
Добавление службы операций CRUD
Добавьте каталог служб в корневой каталог проекта.
BooksService
Добавьте класс в каталог Служб со следующим кодом:using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
В приведенном коде
BookStoreDatabaseSettings
экземпляр извлекается из DI с помощью внедрения через конструктор. Этот метод предоставляет доступ кappsettings.json
значениям конфигурации, добавленным в разделе "Добавление модели конфигурации ".Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
В приведенном выше коде класс
BooksService
регистрируется в DI для поддержки внедрения через конструктор в потребляющие классы. Время существования одноэлементной службы является наиболее подходящим, так какBooksService
находится в прямой зависимости отMongoClient
. В соответствии с официальными рекомендациями по повторному использованию клиента Mongo,MongoClient
следует зарегистрировать в DI с временем жизни службы singleton.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBooksService
.using BookStoreApi.Services;
Класс BooksService
использует следующие MongoDB.Driver
члены для выполнения операций CRUD с базой данных:
MongoClient: использует экземпляр сервера для выполнения операций с базой данных. Конструктор этого класса предоставляется в строке подключения MongoDB:
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: представляет базу данных Mongo для выполнения операций. В этом руководстве используется универсальный метод GetCollection<TDocument>(collection) в интерфейсе для получения доступа к данным в определенной коллекции. Выполните операции CRUD с коллекцией после вызова этого метода. В вызове
GetCollection<TDocument>(collection)
метода:-
collection
представляет имя коллекции. -
TDocument
представляет тип объекта CLR, хранящийся в коллекции.
-
GetCollection<TDocument>(collection)
возвращает объект MongoCollection , представляющий коллекцию. В этом руководстве в коллекции вызываются следующие методы:
- DeleteOneAsync: удаляет один документ, соответствующий указанным условиям поиска.
- Найти<TDocument>: возвращает все документы в коллекции, соответствующие указанным критериям поиска.
- InsertOneAsync: вставляет предоставленный объект в качестве нового документа в коллекцию.
- ReplaceOneAsync: заменяет один документ, соответствующий предоставленным условиям поиска, предоставленным объектом.
Добавление контроллера
BooksController
Добавьте класс в каталог Controllers со следующим кодом:
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
Предыдущий контроллер веб-API:
- Использует класс
BooksService
для выполнения операций CRUD. - Содержит методы действий для поддержки запросов GET, POST, PUT и DELETE HTTP.
- Вызывает CreatedAtAction в методе
Create
действия для возврата HTTP 201 ответа. Код состояния 201 — это стандартный ответ для метода HTTP POST, который создает новый ресурс на сервере.CreatedAtAction
также добавляет заголовокLocation
в ответ. ЗаголовокLocation
задает универсальный код ресурса (URI) только что созданной книги.
Настройка параметров сериализации JSON
В разделе «Тестирование веб-API» необходимо изменить два аспекта, касающихся возвращаемых ответов JSON.
- Имена свойств, оформленные по умолчанию в стиле camelCase, должны быть изменены на оформление в стиле PascalCase в соответствии с именами свойств объекта CLR.
- Свойство
bookName
должно быть возвращено какName
.
Чтобы удовлетворить указанные выше требования, внесите следующие изменения:
В
Program.cs
добавьте следующий выделенный код к вызову методаAddControllers
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
При предыдущем изменении имена свойств в сериализованном ответе JSON веб-API соответствуют соответствующим именам свойств в типе объекта CLR. Например,
Book
свойство классаAuthor
сериализуется какAuthor
вместоauthor
.В
Models/Book.cs
, аннотируйте свойствоBookName
атрибутом[JsonPropertyName]
.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
Значение атрибутаName
представляет имя свойства в сериализованном ответе JSON веб-API.Добавьте следующий код в начало
Models/Book.cs
для разрешения ссылки на атрибут[JsonProperty]
.using System.Text.Json.Serialization;
Повторите действия, определенные в разделе "Тестирование веб-API ". Обратите внимание на разницу в именах свойств JSON.
Тестирование веб-API
В этом руководстве для тестирования API используются обозреватель конечных точек и HTTP-файлы .
Создайте и запустите приложение.
В обозревателе конечных точек щелкните правой кнопкой мыши первую конечную точку
/api/books
и выберите команду "Создать запрос".В файл добавляется следующее содержимое
BookStoreApi.http
. Если это первый раз, когда создается запрос, файл создается в корневом каталоге проекта.@BookStoreApi_HostAddress = https://localhost:<port> GET {{BookStoreApi_HostAddress}}/api/books ###
Номер порта уже должен быть задан для порта, используемого приложением, например
https://localhost:56874
. Если это не так, вы можете найти номер порта в окне вывода при запуске приложения.Выберите ссылку "Отправить запрос " над новой
GET
строкой запроса.Запрос GET отправляется приложению, а ответ отображается в области ответа .
Текст ответа показывает результат JSON, содержащий записи книги, аналогичные следующим:
[ { "Id": "61a6058e6c43f32854e51f51", "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Id": "61a6058e6c43f32854e51f52", "Name": "Clean Code", "Price": 43.15, "Category": "Computers", "Author": "Robert C. Martin" } ]
Чтобы получить одну книгу, щелкните правой кнопкой мыши
/api/books/{id}, params (string id)
конечную точку GET в обозревателе конечных точек и выберите команду "Создать запрос".К файлу добавляется следующее содержимое
BookStoreApi.http
:@id=string GET {{BookStoreApi_HostAddress}}/api/books/{{id}} ###
Замените
id
переменную одним из идентификаторов, возвращенных из предыдущего запроса, например:@id="61a6058e6c43f32854e51f52" GET {{BookStoreApi_HostAddress}}/api/books/{{id}} ###
Выберите ссылку "Отправить запрос " над новой
GET
строкой запроса.Запрос GET отправляется приложению, а ответ отображается в области ответа .
Тело ответа содержит JSON, аналогичный следующему:
{ "Id": "61a6058e6c43f32854e51f52", "Name": "Clean Code", "Price": 43.15, "Category": "Computers", "Author": "Robert C. Martin" }
Чтобы проверить конечную точку POST, щелкните правой
/api/books
кнопкой мыши конечную точку POST и выберите команду "Создать запрос".В файл добавляется следующее содержимое
BookStoreApi.http
:POST {{BookStoreApi_HostAddress}}/api/books Content-Type: application/json { //Book } ###
Замените комментарий Book объектом книги в виде текста запроса JSON:
POST {{BookStoreApi_HostAddress}}/api/books Content-Type: application/json { "Name": "The Pragmatic Programmer", "Price": 49.99, "Category": "Computers", "Author": "Andy Hunt" } ###
Выберите ссылку "Отправить запрос " над строкой
POST
запроса.Запрос POST отправляется в приложение, а ответ отображается в области ответа . Ответ должен содержать только что созданную книгу с назначенным идентификатором.
Наконец, чтобы удалить книгу, щелкните правой кнопкой мыши
/api/books/{id}, params (string id)
конечную точку DELETE и выберите "Создать запрос".К файлу добавляется следующее содержимое
BookStoreApi.http
:DELETE {{BookStoreApi_HostAddress}}/api/Books/{{id}} ###
Замените
id
переменную одним из идентификаторов, возвращенных из предыдущего запроса, и нажмите кнопку "Отправить запрос". Рассмотрим пример.DELETE {{BookStoreApi_HostAddress}}/api/Books/67f417517ce1b36aeab71236 ###
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и SPA, используйте один из следующих способов:
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Это важно
Компания Duende Software может потребовать оплаты лицензионного сбора за использование Duende Identity Server в производственной среде. Дополнительные сведения см. в статье "Миграция из ASP.NET Core в .NET 5 в .NET 6".
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Дополнительные ресурсы
В этом руководстве создается веб-API, который выполняет операции создания, чтения, обновления и удаления (CRUD) в базе данных MongoDB NoSQL.
В этом руководстве вы узнаете, как:
- Настройка MongoDB
- Создание базы данных MongoDB
- Определение коллекции и схемы MongoDB
- Выполнение операций CRUD MongoDB из веб-API
- Настройка сериализации JSON
Предпосылки
Visual Studio 2022 с рабочей нагрузкой ASP.NET и разработка веб-приложений.
Настройка MongoDB
Включите доступ к MongoDB и оболочке MongoDB из любого места на машине разработки (Windows/Linux/macOS):
Скачайте и установите оболочку MongoDB:
- macOS/Linux: выберите каталог для извлечения оболочки MongoDB. Добавьте полученный путь к переменной среды
mongosh
PATH
. - Windows: Оболочка MongoDB (mongosh.exe) установлена в C:\Users\<user>\AppData\Local\Programs\mongosh. Добавьте полученный путь к переменной среды
mongosh.exe
PATH
.
- macOS/Linux: выберите каталог для извлечения оболочки MongoDB. Добавьте полученный путь к переменной среды
Скачайте и установите MongoDB:
- macOS/Linux: проверьте каталог, по которому был установлен MongoDB, обычно в /usr/local/mongodb. Добавьте полученный путь к переменной среды
mongodb
PATH
. - Windows: MongoDB устанавливается в C:\Program Files\MongoDB по умолчанию. Добавьте C:\Program Files\MongoDB\Server\<version_number>\bin в
PATH
переменную среды.
- macOS/Linux: проверьте каталог, по которому был установлен MongoDB, обычно в /usr/local/mongodb. Добавьте полученный путь к переменной среды
Выберите каталог хранилища данных: выберите каталог на компьютере разработки для хранения данных. Если такого каталога нет, создайте его. Оболочка MongoDB не создает новые каталоги:
- macOS/Linux: например,
/usr/local/var/mongodb
. - Windows: например,
C:\\BooksData
.
- macOS/Linux: например,
В командной оболочке ОС (а не в оболочке MongoDB) используйте следующую команду, чтобы подключиться к MongoDB через порт 27017 по умолчанию. Замените
<data_directory_path>
каталог, выбранный на предыдущем шаге.mongod --dbpath <data_directory_path>
Используйте ранее установленную оболочку MongoDB в следующих шагах для создания базы данных, создания коллекций и хранения документов. Дополнительные сведения о командах оболочки MongoDB см. в статье mongosh
.
Откройте экземпляр командной оболочки MongoDB, запуская
mongosh.exe
или выполнив следующую команду в командной оболочке:mongosh
В командной оболочке подключитесь к тестовой базе данных по умолчанию, выполнив следующую команду:
use BookStore
База данных с именем BookStore создается, если она еще не существует. Если база данных существует, его подключение открывается для транзакций.
Создайте коллекцию с помощью следующей
Books
команды:db.createCollection('Books')
Отображается следующий результат:
{ "ok" : 1 }
Определите схему для
Books
коллекции и вставьте два документа с помощью следующей команды:db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
Отображается результат, аналогичный следующему:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Замечание
Результаты
ObjectId
, показанные в предыдущем примере, не будут совпадать с результатами, показанными в командной оболочке.Просмотрите документы в базе данных с помощью следующей команды:
db.Books.find().pretty()
Отображается результат, аналогичный следующему:
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Схема добавляет автоматическое свойство
_id
типаObjectId
для каждого документа.
Создание проекта веб-API ASP.NET Core
Перейдите к файлу>нового>проекта.
Выберите тип проекта веб-API ASP.NET Core и нажмите кнопку "Далее".
Назовите проект BookStoreApi и нажмите кнопку "Далее".
Выберите платформу .NET 8.0 (долгосрочная поддержка) и нажмите кнопку "Создать".
В окне консоли диспетчера пакетов перейдите в корневой каталог проекта. Выполните следующую команду, чтобы установить драйвер .NET для MongoDB:
Install-Package MongoDB.Driver
Добавление модели сущности
Добавьте каталог Models в корневой каталог проекта.
Book
Добавьте класс в каталог Models со следующим кодом:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
В предыдущем классе свойство
Id
выглядит следующим образом:- Требуется для сопоставления объекта CLR с коллекцией MongoDB.
- Отмечено с помощью
[BsonId]
, чтобы сделать это свойство основным ключом документа. - Аннотировано с
[BsonRepresentation(BsonType.ObjectId)]
, чтобы разрешить передачу параметра как типаstring
, вместо структуры ObjectId. Mongo обрабатывает преобразование изstring
вObjectId
.
Свойство
BookName
аннотировано атрибутом[BsonElement]
. Значение атрибутаName
представляет имя свойства в коллекции MongoDB.
Добавление модели конфигурации
Добавьте следующие значения конфигурации базы данных в
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
BookStoreDatabaseSettings
Добавьте класс в каталог Models со следующим кодом:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
BookStoreDatabaseSettings
Предыдущий класс используется для хранения значенийappsettings.json
свойств файлаBookStoreDatabase
. Имена свойств JSON и C# называются идентичными, чтобы упростить процесс сопоставления.Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
В приведенном выше коде экземпляр конфигурации, к которому привязан раздел файла
appsettings.json
, регистрируется в контейнере внедрения зависимостей (DI). Например, свойствоBookStoreDatabaseSettings
объектаConnectionString
заполняется свойствомBookStoreDatabase:ConnectionString
вappsettings.json
.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBookStoreDatabaseSettings
.using BookStoreApi.Models;
Добавление службы операций CRUD
Добавьте каталог служб в корневой каталог проекта.
BooksService
Добавьте класс в каталог Служб со следующим кодом:using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
В приведенном коде
BookStoreDatabaseSettings
экземпляр извлекается из DI с помощью внедрения через конструктор. Этот метод предоставляет доступ кappsettings.json
значениям конфигурации, добавленным в разделе "Добавление модели конфигурации ".Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
В приведенном выше коде класс
BooksService
регистрируется в DI для поддержки внедрения через конструктор в потребляющие классы. Время существования одноэлементной службы является наиболее подходящим, так какBooksService
находится в прямой зависимости отMongoClient
. В соответствии с официальными рекомендациями по повторному использованию клиента Mongo,MongoClient
следует зарегистрировать в DI с временем жизни службы singleton.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBooksService
.using BookStoreApi.Services;
Класс BooksService
использует следующие MongoDB.Driver
члены для выполнения операций CRUD с базой данных:
MongoClient: использует экземпляр сервера для выполнения операций с базой данных. Конструктор этого класса предоставляется в строке подключения MongoDB:
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: представляет базу данных Mongo для выполнения операций. В этом руководстве используется универсальный метод GetCollection<TDocument>(collection) в интерфейсе для получения доступа к данным в определенной коллекции. Выполните операции CRUD с коллекцией после вызова этого метода. В вызове
GetCollection<TDocument>(collection)
метода:-
collection
представляет имя коллекции. -
TDocument
представляет тип объекта CLR, хранящийся в коллекции.
-
GetCollection<TDocument>(collection)
возвращает объект MongoCollection , представляющий коллекцию. В этом руководстве в коллекции вызываются следующие методы:
- DeleteOneAsync: удаляет один документ, соответствующий указанным условиям поиска.
- Найти<TDocument>: возвращает все документы в коллекции, соответствующие указанным критериям поиска.
- InsertOneAsync: вставляет предоставленный объект в качестве нового документа в коллекцию.
- ReplaceOneAsync: заменяет один документ, соответствующий предоставленным условиям поиска, предоставленным объектом.
Добавление контроллера
BooksController
Добавьте класс в каталог Controllers со следующим кодом:
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
Предыдущий контроллер веб-API:
- Использует класс
BooksService
для выполнения операций CRUD. - Содержит методы действий для поддержки запросов GET, POST, PUT и DELETE HTTP.
- Вызывает CreatedAtAction в методе
Create
действия для возврата HTTP 201 ответа. Код состояния 201 — это стандартный ответ для метода HTTP POST, который создает новый ресурс на сервере.CreatedAtAction
также добавляет заголовокLocation
в ответ. ЗаголовокLocation
задает универсальный код ресурса (URI) только что созданной книги.
Тестирование веб-API
Создайте и запустите приложение.
Перейдите в
https://localhost:<port>/api/books
раздел, где<port>
- автоматически назначенный номер порта для приложения, чтобы проверить действие метода без параметровGet
контроллера. Отображается ответ JSON, аналогичный следующему:[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
Перейдите к
https://localhost:<port>/api/books/{id here}
, чтобы протестировать метод действия с перегрузкойGet
контроллера. Отображается ответ JSON, аналогичный следующему:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Настройка параметров сериализации JSON
В разделе «Тестирование веб-API» необходимо изменить два аспекта, касающихся возвращаемых ответов JSON.
- Имена свойств, оформленные по умолчанию в стиле camelCase, должны быть изменены на оформление в стиле PascalCase в соответствии с именами свойств объекта CLR.
- Свойство
bookName
должно быть возвращено какName
.
Чтобы удовлетворить указанные выше требования, внесите следующие изменения:
В
Program.cs
добавьте следующий выделенный код к вызову методаAddControllers
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
При предыдущем изменении имена свойств в сериализованном ответе JSON веб-API соответствуют соответствующим именам свойств в типе объекта CLR. Например,
Book
свойство классаAuthor
сериализуется какAuthor
вместоauthor
.В
Models/Book.cs
, аннотируйте свойствоBookName
атрибутом[JsonPropertyName]
.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
Значение атрибутаName
представляет имя свойства в сериализованном ответе JSON веб-API.Добавьте следующий код в начало
Models/Book.cs
для разрешения ссылки на атрибут[JsonProperty]
.using System.Text.Json.Serialization;
Повторите действия, определенные в разделе "Тестирование веб-API ". Обратите внимание на разницу в именах свойств JSON.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и SPA, используйте один из следующих способов:
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Это важно
Компания Duende Software может потребовать оплаты лицензионного сбора за использование Duende Identity Server в производственной среде. Дополнительные сведения см. в статье "Миграция из ASP.NET Core в .NET 5 в .NET 6".
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Дополнительные ресурсы
В этом руководстве создается веб-API, который выполняет операции создания, чтения, обновления и удаления (CRUD) в базе данных MongoDB NoSQL.
В этом руководстве вы узнаете, как:
- Настройка MongoDB
- Создание базы данных MongoDB
- Определение коллекции и схемы MongoDB
- Выполнение операций CRUD MongoDB из веб-API
- Настройка сериализации JSON
Предпосылки
Visual Studio 2022 с рабочей нагрузкой ASP.NET и разработка веб-приложений.
Настройка MongoDB
Включите доступ к MongoDB и оболочке MongoDB из любой точки компьютера разработки.
В Windows MongoDB по умолчанию устанавливается в C:\Program Files\MongoDB . Добавьте C:\Program Files\MongoDB\Server\<version_number>\bin в
PATH
переменную среды.Скачайте оболочку MongoDB и выберите папку для её извлечения. Добавьте полученный путь к переменной среды
mongosh.exe
PATH
.Выберите каталог на компьютере разработки для хранения данных. Например, C:\BooksData в Windows. Если такого каталога нет, создайте его. Mongo Shell не создает новые каталоги.
В командной оболочке ОС (а не в оболочке MongoDB) используйте следующую команду, чтобы подключиться к MongoDB через порт 27017 по умолчанию. Замените
<data_directory_path>
каталог, выбранный на предыдущем шаге.mongod --dbpath <data_directory_path>
Используйте ранее установленную оболочку MongoDB в следующих шагах для создания базы данных, создания коллекций и хранения документов. Дополнительные сведения о командах оболочки MongoDB см. в статье mongosh
.
Откройте экземпляр командной оболочки MongoDB, запуская
mongosh.exe
или выполнив следующую команду в командной оболочке:mongosh
В командной оболочке подключитесь к тестовой базе данных по умолчанию, выполнив следующую команду:
use BookStore
База данных с именем BookStore создается, если она еще не существует. Если база данных существует, его подключение открывается для транзакций.
Создайте коллекцию с помощью следующей
Books
команды:db.createCollection('Books')
Отображается следующий результат:
{ "ok" : 1 }
Определите схему для
Books
коллекции и вставьте два документа с помощью следующей команды:db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
Отображается результат, аналогичный следующему:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Замечание
Результаты
ObjectId
, показанные в предыдущем примере, не будут совпадать с результатами, показанными в командной оболочке.Просмотрите документы в базе данных с помощью следующей команды:
db.Books.find().pretty()
Отображается результат, аналогичный следующему:
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Схема добавляет автоматическое свойство
_id
типаObjectId
для каждого документа.
Создание проекта веб-API ASP.NET Core
Перейдите к файлу>нового>проекта.
Выберите тип проекта веб-API ASP.NET Core и нажмите кнопку "Далее".
Назовите проект BookStoreApi и нажмите кнопку "Далее".
Выберите платформу .NET 7.0 (стандартная поддержка терминов) и нажмите кнопку "Создать".
В меню "Сервисов" выберите диспетчер пакетов NuGet>Консоль диспетчера пакетов.
В окне консоли диспетчера пакетов перейдите в корневой каталог проекта. Выполните следующую команду, чтобы установить драйвер .NET для MongoDB:
Install-Package MongoDB.Driver
Добавление модели сущности
Добавьте каталог Models в корневой каталог проекта.
Book
Добавьте класс в каталог Models со следующим кодом:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
В предыдущем классе свойство
Id
выглядит следующим образом:- Требуется для сопоставления объекта CLR с коллекцией MongoDB.
- Отмечено с помощью
[BsonId]
, чтобы сделать это свойство основным ключом документа. - Аннотировано с
[BsonRepresentation(BsonType.ObjectId)]
, чтобы разрешить передачу параметра как типаstring
, вместо структуры ObjectId. Mongo обрабатывает преобразование изstring
вObjectId
.
Свойство
BookName
аннотировано атрибутом[BsonElement]
. Значение атрибутаName
представляет имя свойства в коллекции MongoDB.
Добавление модели конфигурации
Добавьте следующие значения конфигурации базы данных в
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
BookStoreDatabaseSettings
Добавьте класс в каталог Models со следующим кодом:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
BookStoreDatabaseSettings
Предыдущий класс используется для хранения значенийappsettings.json
свойств файлаBookStoreDatabase
. Имена свойств JSON и C# называются идентичными, чтобы упростить процесс сопоставления.Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
В приведенном выше коде экземпляр конфигурации, к которому привязан раздел файла
appsettings.json
, регистрируется в контейнере внедрения зависимостей (DI). Например, свойствоBookStoreDatabaseSettings
объектаConnectionString
заполняется свойствомBookStoreDatabase:ConnectionString
вappsettings.json
.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBookStoreDatabaseSettings
.using BookStoreApi.Models;
Добавление службы операций CRUD
Добавьте каталог служб в корневой каталог проекта.
BooksService
Добавьте класс в каталог Служб со следующим кодом:using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
В приведенном коде
BookStoreDatabaseSettings
экземпляр извлекается из DI с помощью внедрения через конструктор. Этот метод предоставляет доступ кappsettings.json
значениям конфигурации, добавленным в разделе "Добавление модели конфигурации ".Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
В приведенном выше коде класс
BooksService
регистрируется в DI для поддержки внедрения через конструктор в потребляющие классы. Время существования одноэлементной службы является наиболее подходящим, так какBooksService
находится в прямой зависимости отMongoClient
. В соответствии с официальными рекомендациями по повторному использованию клиента Mongo,MongoClient
следует зарегистрировать в DI с временем жизни службы singleton.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBooksService
.using BookStoreApi.Services;
Класс BooksService
использует следующие MongoDB.Driver
члены для выполнения операций CRUD с базой данных:
MongoClient: использует экземпляр сервера для выполнения операций с базой данных. Конструктор этого класса получает строку подключения MongoDB.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: представляет базу данных Mongo для выполнения операций. В этом руководстве используется универсальный метод GetCollection<TDocument>(collection) в интерфейсе для получения доступа к данным в определенной коллекции. Выполните операции CRUD с коллекцией после вызова этого метода. В вызове
GetCollection<TDocument>(collection)
метода:-
collection
представляет имя коллекции. -
TDocument
представляет тип объекта CLR, хранящийся в коллекции.
-
GetCollection<TDocument>(collection)
возвращает объект MongoCollection , представляющий коллекцию. В этом руководстве в коллекции вызываются следующие методы:
- DeleteOneAsync: удаляет один документ, соответствующий указанным условиям поиска.
- Найти<TDocument>: возвращает все документы в коллекции, соответствующие указанным критериям поиска.
- InsertOneAsync: вставляет предоставленный объект в качестве нового документа в коллекцию.
- ReplaceOneAsync: заменяет один документ, соответствующий предоставленным условиям поиска, предоставленным объектом.
Добавление контроллера
BooksController
Добавьте класс в каталог Controllers со следующим кодом:
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
Предыдущий контроллер веб-API:
- Использует класс
BooksService
для выполнения операций CRUD. - Содержит методы действий для поддержки запросов GET, POST, PUT и DELETE HTTP.
- Вызывает CreatedAtAction в методе
Create
действия для возврата HTTP 201 ответа. Код состояния 201 — это стандартный ответ для метода HTTP POST, который создает новый ресурс на сервере.CreatedAtAction
также добавляет заголовокLocation
в ответ. ЗаголовокLocation
задает универсальный код ресурса (URI) только что созданной книги.
Тестирование веб-API
Создайте и запустите приложение.
Перейдите в
https://localhost:<port>/api/books
раздел, где<port>
- автоматически назначенный номер порта для приложения, чтобы проверить действие метода без параметровGet
контроллера. Отображается ответ JSON, аналогичный следующему:[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
Перейдите к
https://localhost:<port>/api/books/{id here}
, чтобы протестировать метод действия с перегрузкойGet
контроллера. Отображается ответ JSON, аналогичный следующему:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Настройка параметров сериализации JSON
В разделе «Тестирование веб-API» необходимо изменить два аспекта, касающихся возвращаемых ответов JSON.
- Имена свойств, оформленные по умолчанию в стиле camelCase, должны быть изменены на оформление в стиле PascalCase в соответствии с именами свойств объекта CLR.
- Свойство
bookName
должно быть возвращено какName
.
Чтобы удовлетворить указанные выше требования, внесите следующие изменения:
В
Program.cs
добавьте следующий выделенный код к вызову методаAddControllers
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
При предыдущем изменении имена свойств в сериализованном ответе JSON веб-API соответствуют соответствующим именам свойств в типе объекта CLR. Например,
Book
свойство классаAuthor
сериализуется какAuthor
вместоauthor
.В
Models/Book.cs
, аннотируйте свойствоBookName
атрибутом[JsonPropertyName]
.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
Значение атрибутаName
представляет имя свойства в сериализованном ответе JSON веб-API.Добавьте следующий код в начало
Models/Book.cs
для разрешения ссылки на атрибут[JsonProperty]
.using System.Text.Json.Serialization;
Повторите действия, определенные в разделе "Тестирование веб-API ". Обратите внимание на разницу в именах свойств JSON.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и SPA, используйте один из следующих способов:
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Это важно
Компания Duende Software может потребовать оплаты лицензионного сбора за использование Duende Identity Server в производственной среде. Дополнительные сведения см. в статье "Миграция из ASP.NET Core в .NET 5 в .NET 6".
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Дополнительные ресурсы
В этом руководстве создается веб-API, который выполняет операции создания, чтения, обновления и удаления (CRUD) в базе данных MongoDB NoSQL.
В этом руководстве вы узнаете, как:
- Настройка MongoDB
- Создание базы данных MongoDB
- Определение коллекции и схемы MongoDB
- Выполнение операций CRUD MongoDB из веб-API
- Настройка сериализации JSON
Предпосылки
- Visual Studio 2022 с рабочей нагрузкой ASP.NET и разработка веб-приложений.
- Пакет SDK для .NET 6
Настройка MongoDB
Включите доступ к MongoDB и оболочке MongoDB из любой точки компьютера разработки.
В Windows MongoDB по умолчанию устанавливается в C:\Program Files\MongoDB . Добавьте C:\Program Files\MongoDB\Server\<version_number>\bin в
PATH
переменную среды.Скачайте оболочку MongoDB и выберите папку для её извлечения. Добавьте полученный путь к переменной среды
mongosh.exe
PATH
.Выберите каталог на компьютере разработки для хранения данных. Например, C:\BooksData в Windows. Если такого каталога нет, создайте его. Mongo Shell не создает новые каталоги.
В командной оболочке ОС (а не в оболочке MongoDB) используйте следующую команду, чтобы подключиться к MongoDB через порт 27017 по умолчанию. Замените
<data_directory_path>
каталог, выбранный на предыдущем шаге.mongod --dbpath <data_directory_path>
Используйте ранее установленную оболочку MongoDB в следующих шагах для создания базы данных, создания коллекций и хранения документов. Дополнительные сведения о командах оболочки MongoDB см. в статье mongosh
.
Откройте экземпляр командной оболочки MongoDB, запуская
mongosh.exe
или выполнив следующую команду в командной оболочке:mongosh
В командной оболочке подключитесь к тестовой базе данных по умолчанию, выполнив следующую команду:
use BookStore
База данных с именем BookStore создается, если она еще не существует. Если база данных существует, его подключение открывается для транзакций.
Создайте коллекцию с помощью следующей
Books
команды:db.createCollection('Books')
Отображается следующий результат:
{ "ok" : 1 }
Определите схему для
Books
коллекции и вставьте два документа с помощью следующей команды:db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
Отображается результат, аналогичный следующему:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Замечание
Результаты
ObjectId
, показанные в предыдущем примере, не будут совпадать с результатами, показанными в командной оболочке.Просмотрите документы в базе данных с помощью следующей команды:
db.Books.find().pretty()
Отображается результат, аналогичный следующему:
{ "_id" : ObjectId("61a6058e6c43f32854e51f51"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("61a6058e6c43f32854e51f52"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Схема добавляет автоматическое свойство
_id
типаObjectId
для каждого документа.
Создание проекта веб-API ASP.NET Core
Перейдите к файлу>нового>проекта.
Выберите тип проекта веб-API ASP.NET Core и нажмите кнопку "Далее".
Назовите проект BookStoreApi и нажмите кнопку "Далее".
Выберите платформу .NET 6.0 (долгосрочная поддержка) и нажмите кнопку "Создать".
В окне консоли диспетчера пакетов перейдите в корневой каталог проекта. Выполните следующую команду, чтобы установить драйвер .NET для MongoDB:
Install-Package MongoDB.Driver
Добавление модели сущности
Добавьте каталог Models в корневой каталог проекта.
Book
Добавьте класс в каталог Models со следующим кодом:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BookStoreApi.Models; public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } = null!; public decimal Price { get; set; } public string Category { get; set; } = null!; public string Author { get; set; } = null!; }
В предыдущем классе свойство
Id
выглядит следующим образом:- Требуется для сопоставления объекта CLR с коллекцией MongoDB.
- Отмечено с помощью
[BsonId]
, чтобы сделать это свойство основным ключом документа. - Аннотировано с
[BsonRepresentation(BsonType.ObjectId)]
, чтобы разрешить передачу параметра как типаstring
, вместо структуры ObjectId. Mongo обрабатывает преобразование изstring
вObjectId
.
Свойство
BookName
аннотировано атрибутом[BsonElement]
. Значение атрибутаName
представляет имя свойства в коллекции MongoDB.
Добавление модели конфигурации
Добавьте следующие значения конфигурации базы данных в
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
BookStoreDatabaseSettings
Добавьте класс в каталог Models со следующим кодом:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
BookStoreDatabaseSettings
Предыдущий класс используется для хранения значенийappsettings.json
свойств файлаBookStoreDatabase
. Имена свойств JSON и C# называются идентичными, чтобы упростить процесс сопоставления.Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
В приведенном выше коде экземпляр конфигурации, к которому привязан раздел файла
appsettings.json
, регистрируется в контейнере внедрения зависимостей (DI). Например, свойствоBookStoreDatabaseSettings
объектаConnectionString
заполняется свойствомBookStoreDatabase:ConnectionString
вappsettings.json
.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBookStoreDatabaseSettings
.using BookStoreApi.Models;
Добавление службы операций CRUD
Добавьте каталог служб в корневой каталог проекта.
BooksService
Добавьте класс в каталог Служб со следующим кодом:using BookStoreApi.Models; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BookStoreApi.Services; public class BooksService { private readonly IMongoCollection<Book> _booksCollection; public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); } public async Task<List<Book>> GetAsync() => await _booksCollection.Find(_ => true).ToListAsync(); public async Task<Book?> GetAsync(string id) => await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync(); public async Task CreateAsync(Book newBook) => await _booksCollection.InsertOneAsync(newBook); public async Task UpdateAsync(string id, Book updatedBook) => await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook); public async Task RemoveAsync(string id) => await _booksCollection.DeleteOneAsync(x => x.Id == id); }
В приведенном коде
BookStoreDatabaseSettings
экземпляр извлекается из DI с помощью внедрения через конструктор. Этот метод предоставляет доступ кappsettings.json
значениям конфигурации, добавленным в разделе "Добавление модели конфигурации ".Добавьте указанный выделенный код в
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
В приведенном выше коде класс
BooksService
регистрируется в DI для поддержки внедрения через конструктор в потребляющие классы. Время существования одноэлементной службы является наиболее подходящим, так какBooksService
находится в прямой зависимости отMongoClient
. В соответствии с официальными рекомендациями по повторному использованию клиента Mongo,MongoClient
следует зарегистрировать в DI с временем жизни службы singleton.Добавьте следующий код в начало
Program.cs
, чтобы разрешить ссылкуBooksService
.using BookStoreApi.Services;
Класс BooksService
использует следующие MongoDB.Driver
члены для выполнения операций CRUD с базой данных:
MongoClient: использует экземпляр сервера для выполнения операций с базой данных. Конструктор этого класса получает строку подключения MongoDB.
public BooksService( IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings) { var mongoClient = new MongoClient( bookStoreDatabaseSettings.Value.ConnectionString); var mongoDatabase = mongoClient.GetDatabase( bookStoreDatabaseSettings.Value.DatabaseName); _booksCollection = mongoDatabase.GetCollection<Book>( bookStoreDatabaseSettings.Value.BooksCollectionName); }
IMongoDatabase: представляет базу данных Mongo для выполнения операций. В этом руководстве используется универсальный метод GetCollection<TDocument>(collection) в интерфейсе для получения доступа к данным в определенной коллекции. Выполните операции CRUD с коллекцией после вызова этого метода. В вызове
GetCollection<TDocument>(collection)
метода:-
collection
представляет имя коллекции. -
TDocument
представляет тип объекта CLR, хранящийся в коллекции.
-
GetCollection<TDocument>(collection)
возвращает объект MongoCollection , представляющий коллекцию. В этом руководстве в коллекции вызываются следующие методы:
- DeleteOneAsync: удаляет один документ, соответствующий указанным условиям поиска.
- Найти<TDocument>: возвращает все документы в коллекции, соответствующие указанным критериям поиска.
- InsertOneAsync: вставляет предоставленный объект в качестве нового документа в коллекцию.
- ReplaceOneAsync: заменяет один документ, соответствующий предоставленным условиям поиска, предоставленным объектом.
Добавление контроллера
BooksController
Добавьте класс в каталог Controllers со следующим кодом:
using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace BookStoreApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BooksService _booksService;
public BooksController(BooksService booksService) =>
_booksService = booksService;
[HttpGet]
public async Task<List<Book>> Get() =>
await _booksService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Book>> Get(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
return book;
}
[HttpPost]
public async Task<IActionResult> Post(Book newBook)
{
await _booksService.CreateAsync(newBook);
return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Book updatedBook)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
updatedBook.Id = book.Id;
await _booksService.UpdateAsync(id, updatedBook);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var book = await _booksService.GetAsync(id);
if (book is null)
{
return NotFound();
}
await _booksService.RemoveAsync(id);
return NoContent();
}
}
Предыдущий контроллер веб-API:
- Использует класс
BooksService
для выполнения операций CRUD. - Содержит методы действий для поддержки запросов GET, POST, PUT и DELETE HTTP.
- Вызывает CreatedAtAction в методе
Create
действия для возврата HTTP 201 ответа. Код состояния 201 — это стандартный ответ для метода HTTP POST, который создает новый ресурс на сервере.CreatedAtAction
также добавляет заголовокLocation
в ответ. ЗаголовокLocation
задает универсальный код ресурса (URI) только что созданной книги.
Тестирование веб-API
Создайте и запустите приложение.
Перейдите в
https://localhost:<port>/api/books
раздел, где<port>
- автоматически назначенный номер порта для приложения, чтобы проверить действие метода без параметровGet
контроллера. Отображается ответ JSON, аналогичный следующему:[ { "id": "61a6058e6c43f32854e51f51", "bookName": "Design Patterns", "price": 54.93, "category": "Computers", "author": "Ralph Johnson" }, { "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" } ]
Перейдите к
https://localhost:<port>/api/books/{id here}
, чтобы протестировать метод действия с перегрузкойGet
контроллера. Отображается ответ JSON, аналогичный следующему:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Настройка параметров сериализации JSON
В разделе «Тестирование веб-API» необходимо изменить два аспекта, касающихся возвращаемых ответов JSON.
- Имена свойств, оформленные по умолчанию в стиле camelCase, должны быть изменены на оформление в стиле PascalCase в соответствии с именами свойств объекта CLR.
- Свойство
bookName
должно быть возвращено какName
.
Чтобы удовлетворить указанные выше требования, внесите следующие изменения:
В
Program.cs
добавьте следующий выделенный код к вызову методаAddControllers
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>(); builder.Services.AddControllers() .AddJsonOptions( options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
При предыдущем изменении имена свойств в сериализованном ответе JSON веб-API соответствуют соответствующим именам свойств в типе объекта CLR. Например,
Book
свойство классаAuthor
сериализуется какAuthor
вместоauthor
.В
Models/Book.cs
, аннотируйте свойствоBookName
атрибутом[JsonPropertyName]
.[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
[JsonPropertyName]
Значение атрибутаName
представляет имя свойства в сериализованном ответе JSON веб-API.Добавьте следующий код в начало
Models/Book.cs
для разрешения ссылки на атрибут[JsonProperty]
.using System.Text.Json.Serialization;
Повторите действия, определенные в разделе "Тестирование веб-API ". Обратите внимание на разницу в именах свойств JSON.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и SPA, используйте один из следующих способов:
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Это важно
Компания Duende Software может потребовать оплаты лицензионного сбора за использование Duende Identity Server в производственной среде. Дополнительные сведения см. в статье "Миграция из ASP.NET Core в .NET 5 в .NET 6".
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Дополнительные ресурсы
В этом руководстве создается веб-API, который выполняет операции создания, чтения, обновления и удаления (CRUD) в базе данных MongoDB NoSQL.
В этом руководстве вы узнаете, как:
- Настройка MongoDB
- Создание базы данных MongoDB
- Определение коллекции и схемы MongoDB
- Выполнение операций CRUD MongoDB из веб-API
- Настройка сериализации JSON
Просмотр или скачивание примера кода (как скачать)
Предпосылки
- Пакет SDK для .NET Core 3.0 или более поздней версии
- Visual Studio 2019 с рабочей нагрузкой ASP.NET и веб-разработка.
- Система MongoDB
Настройка MongoDB
При использовании Windows MongoDB устанавливается по умолчанию в C:\Program Files\MongoDB . Добавьте C:\Program Files\MongoDB\Server\<version_number>\bin в Path
переменную среды. Это изменение позволяет MongoDB получать доступ из любого места на компьютере разработки.
Используйте mongo Shell в следующих шагах для создания базы данных, создания коллекций и хранения документов. Дополнительные сведения о командах mongo Shell см. в статье "Работа с mongo Shell".
Выберите каталог на компьютере разработки для хранения данных. Например, C:\BooksData в Windows. Если такого каталога нет, создайте его. Mongo Shell не создает новые каталоги.
Откройте командную оболочку. Выполните следующую команду, чтобы подключиться к MongoDB через порт 27017 по умолчанию. Не забудьте заменить
<data_directory_path>
на каталог, выбранный на предыдущем шаге.mongod --dbpath <data_directory_path>
Откройте другой экземпляр командной оболочки. Подключитесь к тестовой базе данных по умолчанию, выполнив следующую команду:
mongo
Выполните следующую команду в командной оболочке:
use BookstoreDb
База данных с именем BookstoreDb создается, если она еще не существует. Если база данных существует, его подключение открывается для транзакций.
Создайте коллекцию с помощью следующей
Books
команды:db.createCollection('Books')
Отображается следующий результат:
{ "ok" : 1 }
Определите схему для
Books
коллекции и вставьте два документа с помощью следующей команды:db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])
Отображается следующий результат:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("5bfd996f7b8e48dc15ff215d"), ObjectId("5bfd996f7b8e48dc15ff215e") ] }
Замечание
Идентификаторы, показанные в этой статье, не будут соответствовать идентификаторам при запуске этого примера.
Просмотрите документы в базе данных с помощью следующей команды:
db.Books.find({}).pretty()
Отображается следующий результат:
{ "_id" : ObjectId("5bfd996f7b8e48dc15ff215d"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" } { "_id" : ObjectId("5bfd996f7b8e48dc15ff215e"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
Схема добавляет автоматическое свойство
_id
типаObjectId
для каждого документа.
База данных готова. Вы можете приступить к созданию веб-API ASP.NET Core.
Создание проекта веб-API ASP.NET Core
Перейдите к файлу>нового>проекта.
Выберите тип проекта ASP.NET Core Web Application и нажмите кнопку "Далее".
Назовите проект BooksApi и нажмите кнопку "Создать".
Выберите целевую платформу .NET Core и ASP.NET Core 3.0. Выберите шаблон проекта API и выберите Создать.
Посетите коллекцию NuGet: MongoDB.Driver , чтобы определить последнюю стабильную версию драйвера .NET для MongoDB. В окне консоли диспетчера пакетов перейдите в корневой каталог проекта. Выполните следующую команду, чтобы установить драйвер .NET для MongoDB:
Install-Package MongoDB.Driver -Version {VERSION}
Добавление модели сущности
Добавьте каталог Models в корневой каталог проекта.
Book
Добавьте класс в каталог Models со следующим кодом:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace BooksApi.Models { public class Book { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } [BsonElement("Name")] public string BookName { get; set; } public decimal Price { get; set; } public string Category { get; set; } public string Author { get; set; } } }
В предыдущем классе свойство
Id
выглядит следующим образом:- Требуется для сопоставления объекта CLR с коллекцией MongoDB.
- Отмечено с помощью
[BsonId]
, чтобы сделать это свойство основным ключом документа. - Аннотировано с
[BsonRepresentation(BsonType.ObjectId)]
, чтобы разрешить передачу параметра как типаstring
, вместо структуры ObjectId. Mongo обрабатывает преобразование изstring
вObjectId
.
Свойство
BookName
аннотировано атрибутом[BsonElement]
. Значение атрибутаName
представляет имя свойства в коллекции MongoDB.
Добавление модели конфигурации
Добавьте следующие значения конфигурации базы данных в
appsettings.json
:{ "BookstoreDatabaseSettings": { "BooksCollectionName": "Books", "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookstoreDb" }, "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } } }
BookstoreDatabaseSettings.cs
Добавьте файл в каталог Models со следующим кодом:namespace BooksApi.Models { public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings { public string BooksCollectionName { get; set; } public string ConnectionString { get; set; } public string DatabaseName { get; set; } } public interface IBookstoreDatabaseSettings { string BooksCollectionName { get; set; } string ConnectionString { get; set; } string DatabaseName { get; set; } } }
BookstoreDatabaseSettings
Предыдущий класс используется для хранения значенийappsettings.json
свойств файлаBookstoreDatabaseSettings
. Имена свойств JSON и C# называются идентичными, чтобы упростить процесс сопоставления.Добавьте указанный выделенный код в
Startup.ConfigureServices
:public void ConfigureServices(IServiceCollection services) { // requires using Microsoft.Extensions.Options services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddControllers(); }
В предыдущем коде:
- Экземпляр конфигурации, к которому привязан раздел
appsettings.json
файлаBookstoreDatabaseSettings
, регистрируется в контейнере внедрения зависимостей (Dependency Injection, DI). Например, объектBookstoreDatabaseSettings
обладает свойствомConnectionString
, которое заполняется свойствомBookstoreDatabaseSettings:ConnectionString
вappsettings.json
. - Интерфейс
IBookstoreDatabaseSettings
регистрируется в di с одним временем существования службы. При внедрении экземпляр интерфейса преобразуется вBookstoreDatabaseSettings
объект.
- Экземпляр конфигурации, к которому привязан раздел
Добавьте следующий код в верхнюю часть
Startup.cs
для разрешенияBookstoreDatabaseSettings
иIBookstoreDatabaseSettings
ссылок:using BooksApi.Models;
Добавление службы операций CRUD
Добавьте каталог служб в корневой каталог проекта.
BookService
Добавьте класс в каталог Служб со следующим кодом:using BooksApi.Models; using MongoDB.Driver; using System.Collections.Generic; using System.Linq; namespace BooksApi.Services { public class BookService { private readonly IMongoCollection<Book> _books; public BookService(IBookstoreDatabaseSettings settings) { var client = new MongoClient(settings.ConnectionString); var database = client.GetDatabase(settings.DatabaseName); _books = database.GetCollection<Book>(settings.BooksCollectionName); } public List<Book> Get() => _books.Find(book => true).ToList(); public Book Get(string id) => _books.Find<Book>(book => book.Id == id).FirstOrDefault(); public Book Create(Book book) { _books.InsertOne(book); return book; } public void Update(string id, Book bookIn) => _books.ReplaceOne(book => book.Id == id, bookIn); public void Remove(Book bookIn) => _books.DeleteOne(book => book.Id == bookIn.Id); public void Remove(string id) => _books.DeleteOne(book => book.Id == id); } }
В приведенном выше коде экземпляр
IBookstoreDatabaseSettings
получен из DI через инъекцию в конструктор. Этот метод предоставляет доступ кappsettings.json
значениям конфигурации, добавленным в разделе "Добавление модели конфигурации ".Добавьте указанный выделенный код в
Startup.ConfigureServices
:public void ConfigureServices(IServiceCollection services) { services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddSingleton<BookService>(); services.AddControllers(); }
В приведенном выше коде класс
BookService
регистрируется в DI для поддержки внедрения через конструктор в потребляющие классы. Время существования одноэлементной службы является наиболее подходящим, так какBookService
находится в прямой зависимости отMongoClient
. В соответствии с официальными рекомендациями по повторному использованию клиента Mongo,MongoClient
следует зарегистрировать в DI с временем жизни службы singleton.Добавьте следующий код в начало
Startup.cs
, чтобы разрешить ссылкуBookService
.using BooksApi.Services;
Класс BookService
использует следующие MongoDB.Driver
члены для выполнения операций CRUD с базой данных:
MongoClient: использует экземпляр сервера для выполнения операций с базой данных. Конструктор этого класса получает строку подключения MongoDB.
public BookService(IBookstoreDatabaseSettings settings) { var client = new MongoClient(settings.ConnectionString); var database = client.GetDatabase(settings.DatabaseName); _books = database.GetCollection<Book>(settings.BooksCollectionName); }
IMongoDatabase: представляет базу данных Mongo для выполнения операций. В этом руководстве используется универсальный метод GetCollection<TDocument>(collection) в интерфейсе для получения доступа к данным в определенной коллекции. Выполните операции CRUD с коллекцией после вызова этого метода. В вызове
GetCollection<TDocument>(collection)
метода:-
collection
представляет имя коллекции. -
TDocument
представляет тип объекта CLR, хранящийся в коллекции.
-
GetCollection<TDocument>(collection)
возвращает объект MongoCollection , представляющий коллекцию. В этом руководстве в коллекции вызываются следующие методы:
- DeleteOne: удаляет один документ, соответствующий заданным критериям поиска.
- Найти<TDocument>: возвращает все документы в коллекции, соответствующие указанным критериям поиска.
- InsertOne: вставляет предоставленный объект в качестве нового документа в коллекцию.
- ReplaceOne: заменяет один документ, соответствующий предоставленным условиям поиска, предоставленным объектом.
Добавление контроллера
BooksController
Добавьте класс в каталог Controllers со следующим кодом:
using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace BooksApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;
public BooksController(BookService bookService)
{
_bookService = bookService;
}
[HttpGet]
public ActionResult<List<Book>> Get() =>
_bookService.Get();
[HttpGet("{id:length(24)}", Name = "GetBook")]
public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
return book;
}
[HttpPost]
public ActionResult<Book> Create(Book book)
{
_bookService.Create(book);
return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
}
[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Update(id, bookIn);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Remove(id);
return NoContent();
}
}
}
Предыдущий контроллер веб-API:
- Использует класс
BookService
для выполнения операций CRUD. - Содержит методы действий для поддержки запросов GET, POST, PUT и DELETE HTTP.
- Вызывает CreatedAtRoute в методе
Create
действия для возврата HTTP 201 ответа. Код состояния 201 — это стандартный ответ для метода HTTP POST, который создает новый ресурс на сервере.CreatedAtRoute
также добавляет заголовокLocation
в ответ. ЗаголовокLocation
задает универсальный код ресурса (URI) только что созданной книги.
Тестирование веб-API
Создайте и запустите приложение.
Перейдите к
https://localhost:<port>/api/books
, чтобы протестировать метод действия контроллераGet
без параметров. Отображается следующий ответ JSON:[ { "id":"5bfd996f7b8e48dc15ff215d", "bookName":"Design Patterns", "price":54.93, "category":"Computers", "author":"Ralph Johnson" }, { "id":"5bfd996f7b8e48dc15ff215e", "bookName":"Clean Code", "price":43.15, "category":"Computers", "author":"Robert C. Martin" } ]
Перейдите к
https://localhost:<port>/api/books/{id here}
, чтобы протестировать метод действия с перегрузкойGet
контроллера. Отображается следующий ответ JSON:{ "id":"{ID}", "bookName":"Clean Code", "price":43.15, "category":"Computers", "author":"Robert C. Martin" }
Настройка параметров сериализации JSON
В разделе «Тестирование веб-API» необходимо изменить два аспекта, касающихся возвращаемых ответов JSON.
- Имена свойств, оформленные по умолчанию в стиле camelCase, должны быть изменены на оформление в стиле PascalCase в соответствии с именами свойств объекта CLR.
- Свойство
bookName
должно быть возвращено какName
.
Чтобы удовлетворить указанные выше требования, внесите следующие изменения:
Json.NET удалены из ASP.NET общей платформы. Добавьте ссылку на пакет для
Microsoft.AspNetCore.Mvc.NewtonsoftJson
.В
Startup.ConfigureServices
добавьте следующий выделенный код к вызову методаAddControllers
:public void ConfigureServices(IServiceCollection services) { services.Configure<BookstoreDatabaseSettings>( Configuration.GetSection(nameof(BookstoreDatabaseSettings))); services.AddSingleton<IBookstoreDatabaseSettings>(sp => sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value); services.AddSingleton<BookService>(); services.AddControllers() .AddNewtonsoftJson(options => options.UseMemberCasing()); }
При предыдущем изменении имена свойств в сериализованном ответе JSON веб-API соответствуют соответствующим именам свойств в типе объекта CLR. Например, свойство
Book
классаAuthor
сериализуется какAuthor
.В
Models/Book.cs
аннотируйте свойствоBookName
следующими атрибутами[JsonProperty]
:[BsonElement("Name")] [JsonProperty("Name")] public string BookName { get; set; }
[JsonProperty]
Значение атрибутаName
представляет имя свойства в сериализованном ответе JSON веб-API.Добавьте следующий код в начало
Models/Book.cs
для разрешения ссылки на атрибут[JsonProperty]
.using Newtonsoft.Json;
Повторите действия, определенные в разделе "Тестирование веб-API ". Обратите внимание на разницу в именах свойств JSON.
Добавление поддержки аутентификации в веб-API
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и SPA, используйте один из следующих способов:
- Идентификатор Microsoft Entra
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer — это сторонний продукт.
Duende IdentityServer — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende IdentityServer включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Дополнительные сведения см. в разделе "Обзор Duende IdentityServer".
Дополнительные сведения о других поставщиках проверки подлинности см. в разделе "Параметры проверки подлинности Community OSS" для ASP.NET Core
Дальнейшие шаги
Дополнительные сведения о создании веб-API ASP.NET Core см. в следующих ресурсах:
ASP.NET Core