Creare un'API Web con ASP.NET Core e MongoDB
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Di Pratik Khandelwal e Scott Addie
Questa esercitazione crea un'API Web che esegue operazioni Create, Read, Update e Delete (CRUD) in un database NoSQL mongoDB .
In questa esercitazione apprenderai a:
- Configurare MongoDB
- Creare un database MongoDB
- Definire una raccolta e uno schema MongoDB
- Eseguire operazioni CRUD di MongoDB da un'API Web
- Personalizzare la serializzazione JSON
Prerequisiti
Visual Studio 2022 con il carico di lavoro Sviluppo ASP.NET e Web.
Configurare MongoDB
Abilitare l'accesso alla shell MongoDB e MongoDB da qualsiasi punto del computer di sviluppo (Windows/Linux/macOS):
Scaricare e installare MongoDB Shell:
- macOS/Linux: scegliere una directory in cui estrarre la shell mongoDB. Aggiungere il percorso risultante per
mongosh
allaPATH
variabile di ambiente. - Windows: MongoDB Shell (mongosh.exe) è installato in C:\Users<user>\AppData\Local\Programs\mongosh. Aggiungere il percorso risultante per
mongosh.exe
allaPATH
variabile di ambiente.
- macOS/Linux: scegliere una directory in cui estrarre la shell mongoDB. Aggiungere il percorso risultante per
Scaricare e installare MongoDB:
- macOS/Linux: verificare che la directory in cui MongoDB sia installato, in genere in /usr/local/mongodb. Aggiungere il percorso risultante per
mongodb
allaPATH
variabile di ambiente. - Windows: MongoDB è installato in C:\Programmi\MongoDB per impostazione predefinita. Aggiungere C:\Programmi\MongoDB\Server\<version_number>\bin alla
PATH
variabile di ambiente.
- macOS/Linux: verificare che la directory in cui MongoDB sia installato, in genere in /usr/local/mongodb. Aggiungere il percorso risultante per
Scegliere una directory di archiviazione dati: selezionare una directory nel computer di sviluppo per l'archiviazione dei dati. Creare la directory se non esiste. La shell mongoDB non crea nuove directory:
- macOS/Linux: ad esempio.
/usr/local/var/mongodb
- Windows: ad esempio.
C:\\BooksData
- macOS/Linux: ad esempio.
Nella shell dei comandi del sistema operativo (non nella shell mongoDB) usare il comando seguente per connettersi a MongoDB sulla porta predefinita 27017. Sostituire
<data_directory_path>
con la directory scelta nel passaggio precedente.mongod --dbpath <data_directory_path>
Usare la shell MongoDB installata in precedenza nei passaggi seguenti per creare un database, creare raccolte e archiviare documenti. Per altre informazioni sui comandi della shell mongoDB, vedere mongosh
.
Aprire un'istanza della shell dei comandi mongoDB avviando
mongosh.exe
.Nella shell dei comandi connettersi al database di test predefinito eseguendo il comando seguente:
mongosh
Eseguire il comando seguente nella shell dei comandi:
use BookStore
Se non esiste già, viene creato un database denominato BookStore . Se il database esiste, la connessione viene aperta per le transazioni.
Creare una raccolta
Books
tramite il comando seguente:db.createCollection('Books')
Viene visualizzato il risultato seguente:
{ "ok" : 1 }
Definire uno schema per la raccolta
Books
e inserire due documenti usando il comando seguente: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" }])
Viene visualizzato un risultato simile al seguente:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Nota
I
ObjectId
valori visualizzati nel risultato precedente non corrispondono a quelli visualizzati nella shell dei comandi.Visualizzare i documenti nel database usando il comando seguente:
db.Books.find().pretty()
Viene visualizzato un risultato simile al seguente:
{ "_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" }
Lo schema aggiunge una proprietà
_id
generata automaticamente di tipoObjectId
per ogni documento.
Creare il progetto per l'API Web ASP.NET Core
- Passare a File>Nuovo>Progetto.
- Selezionare il tipo di progetto API Web core ASP.NET e selezionare Avanti.
- Assegnare al progetto il nome BookStoreApi e selezionare Avanti.
- Nella finestra di dialogo informazioni aggiuntive:
- Verificare che il di
Framework sia .NET 9.0 (supporto standard per termini) . - Verificare che sia selezionata la casella di controllo Usa controller.
- Verificare che sia selezionata la casella di controllo per Abilitare il supporto OpenAPI.
- Selezionare Crea.
Nella finestra Console di Gestione pacchetti passare alla radice del progetto. Eseguire il comando seguente per installare il driver .NET per MongoDB:
Install-Package MongoDB.Driver
Aggiungere un modello di entità
Aggiungere una directory Models alla radice del progetto.
Aggiungere una classe
Book
alla directory Models con il codice seguente: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!; }
Nella classe precedente la
Id
proprietà è:- Obbligatorio per eseguire il mapping dell'oggetto Common Language Runtime (CLR) all'insieme MongoDB.
- Annotato con
[BsonId]
per impostare questa proprietà sulla chiave primaria del documento. - Annotato con
[BsonRepresentation(BsonType.ObjectId)]
per consentire il passaggio del parametro come tipostring
invece di una struttura ObjectId . Mongo gestisce la conversione dastring
aObjectId
.
La
BookName
proprietà viene annotata con l'attributo[BsonElement]
. Il valore dell'attributoName
rappresenta il nome della proprietà nella raccolta MongoDB.
Aggiungere un modello di configurazione
Aggiungere i valori di configurazione del database seguenti a
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Aggiungere una classe
BookStoreDatabaseSettings
alla directory Models con il codice seguente:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
La classe precedente
BookStoreDatabaseSettings
viene usata per archiviare iappsettings.json
valori delle proprietà delBookStoreDatabase
file. I nomi delle proprietà JSON e C# sono identici per semplificare il processo di mapping.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
Nel codice precedente, l'istanza di configurazione a cui viene associata la
appsettings.json
sezione delBookStoreDatabase
file viene registrata nel contenitore Inserimento dipendenze . Ad esempio, laBookStoreDatabaseSettings
proprietà dell'oggettoConnectionString
viene popolata con laBookStoreDatabase:ConnectionString
proprietà inappsettings.json
.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBookStoreDatabaseSettings
riferimento:using BookStoreApi.Models;
Aggiungere un servizio di operazioni CRUD
Aggiungere una directory Services alla radice del progetto.
Aggiungere una classe
BooksService
alla directory Services con il codice seguente: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); }
Nel codice precedente, un'istanza
BookStoreDatabaseSettings
viene recuperata dall'inserimento delle dipendenze tramite l'inserimento del costruttore. Questa tecnica consente di accedere ai valori diappsettings.json
configurazione aggiunti nella sezione Aggiungere un modello di configurazione.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
Nel codice precedente la classe
BooksService
è registrata con l'inserimento di dipendenze per supportare l'inserimento del costruttore nelle classi che la utilizzano. La durata del servizio singleton è più appropriata perchéBooksService
assume una dipendenza diretta aMongoClient
. In base alle linee guida per il riutilizzo di Mongo Client ufficiali,MongoClient
deve essere registrato nell'inserimento di dipendenze con una durata del servizio singleton.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBooksService
riferimento:using BookStoreApi.Services;
La BooksService
classe usa i membri seguenti MongoDB.Driver
per eseguire operazioni CRUD sul database:
MongoClient: legge l'istanza del server per l'esecuzione di operazioni di database. Il costruttore di questa classe viene fornito nel stringa di connessione 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: rappresenta il database Mongo per l'esecuzione delle operazioni. Questa esercitazione usa il metodo getCollection<TDocument>(collection) generico sull'interfaccia per ottenere l'accesso ai dati in una raccolta specifica. Eseguire operazioni CRUD sulla raccolta dopo la chiamata di questo metodo. Nella chiamata del metodo
GetCollection<TDocument>(collection)
:-
collection
rappresenta il nome della raccolta. -
TDocument
rappresenta il tipo di oggetto CLR archiviato nella raccolta.
-
GetCollection<TDocument>(collection)
restituisce un oggetto MongoCollection che rappresenta la raccolta. In questa esercitazione, vengono richiamati i metodi seguenti sulla raccolta:
- DeleteOneAsync: elimina un singolo documento corrispondente ai criteri di ricerca specificati.
- Trova<TDocument>: restituisce tutti i documenti nella raccolta che corrispondono ai criteri di ricerca specificati.
- InsertOneAsync: inserisce l'oggetto fornito come nuovo documento nell'insieme.
- ReplaceOneAsync: sostituisce il singolo documento corrispondente ai criteri di ricerca specificati con l'oggetto specificato.
Aggiungere un controller
Aggiungere una classe BooksController
alla directory Controllers con il codice seguente:
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();
}
}
Il controller dell'API Web precedente:
- Usa la
BooksService
classe per eseguire operazioni CRUD. - Contiene metodi di azione per supportare le richieste HTTP GET, POST, PUT e DELETE.
- Chiama CreatedAtAction nel metodo dell'azione
Create
per restituire una risposta HTTP 201. Il codice di stato 201 è la risposta standard per un metodo HTTP POST che crea una nuova risorsa nel server.CreatedAtAction
aggiunge anche un'intestazioneLocation
alla risposta. L'intestazioneLocation
specifica l'URI del libro appena creato.
Testare l'API Web
Compilare ed eseguire l'app.
Passare a
https://localhost:<port>/api/books
, dove<port>
è il numero di porta assegnato automaticamente per l'app, per testare il metodo di azione senzaGet
parametri del controller, selezionare Prova esegui>. Viene visualizzata una risposta JSON simile alla seguente:[ { "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" } ]
Passare a
https://localhost:<port>/api/books/{id here}
per testare il metodo dell'azioneGet
in overload del controller. Viene visualizzata una risposta JSON simile alla seguente:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Configurare le opzioni di serializzazione JSON
Esistono due dettagli da modificare per le risposte JSON restituite nella sezione Testare l'API Web:
- La notazione a cammello predefinita per i nomi di proprietà deve essere modificata in modo da adottare la convenzione Pascal dei nomi di proprietà dell'oggetto CLR.
- La proprietà
bookName
deve essere restituita comeName
.
Per soddisfare i requisiti precedenti, apportare le modifiche seguenti:
In
Program.cs
concatenare il codice evidenziato seguente alla chiamata del metodoAddControllers
: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);
Con la modifica precedente, i nomi delle proprietà nella risposta JSON serializzata dell'API Web corrispondono ai nomi di proprietà corrispondenti nel tipo di oggetto CLR. Ad esempio, la
Book
proprietà dellaAuthor
classe serializza comeAuthor
anzichéauthor
.In
Models/Book.cs
annotare laBookName
proprietà con l'attributo[JsonPropertyName]
:[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
Il valore
[JsonPropertyName]
dell'attributoName
rappresenta il nome della proprietà nella risposta JSON serializzata dell'API Web.Aggiungere il codice seguente all'inizio di
Models/Book.cs
per risolvere il riferimento all'attributo[JsonProperty]
:using System.Text.Json.Serialization;
Ripetere i passaggi definiti nella sezione Testare l'API Web. Si noti la differenza nei nomi di proprietà JSON.
Aggiungere il supporto per l'autenticazione a un'API Web
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende Identity Server abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Importante
Duende Software potrebbe richiedere il pagamento di una tariffa di licenza per l'uso in produzione di Duende Identity Server. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.
Per altre informazioni, vedere la documentazione di Duende Server (sito Web duende Identity Software).
Risorse aggiuntive
Questa esercitazione crea un'API Web che esegue operazioni Create, Read, Update e Delete (CRUD) in un database NoSQL mongoDB .
In questa esercitazione apprenderai a:
- Configurare MongoDB
- Creare un database MongoDB
- Definire una raccolta e uno schema MongoDB
- Eseguire operazioni CRUD di MongoDB da un'API Web
- Personalizzare la serializzazione JSON
Prerequisiti
Visual Studio 2022 con il carico di lavoro Sviluppo ASP.NET e Web.
Configurare MongoDB
Abilitare l'accesso alla shell MongoDB e MongoDB da qualsiasi punto del computer di sviluppo (Windows/Linux/macOS):
Scaricare e installare MongoDB Shell:
- macOS/Linux: scegliere una directory in cui estrarre la shell mongoDB. Aggiungere il percorso risultante per
mongosh
allaPATH
variabile di ambiente. - Windows: MongoDB Shell (mongosh.exe) è installato in C:\Users<user>\AppData\Local\Programs\mongosh. Aggiungere il percorso risultante per
mongosh.exe
allaPATH
variabile di ambiente.
- macOS/Linux: scegliere una directory in cui estrarre la shell mongoDB. Aggiungere il percorso risultante per
Scaricare e installare MongoDB:
- macOS/Linux: verificare che la directory in cui MongoDB sia installato, in genere in /usr/local/mongodb. Aggiungere il percorso risultante per
mongodb
allaPATH
variabile di ambiente. - Windows: MongoDB è installato in C:\Programmi\MongoDB per impostazione predefinita. Aggiungere C:\Programmi\MongoDB\Server\<version_number>\bin alla
PATH
variabile di ambiente.
- macOS/Linux: verificare che la directory in cui MongoDB sia installato, in genere in /usr/local/mongodb. Aggiungere il percorso risultante per
Scegliere una directory di archiviazione dati: selezionare una directory nel computer di sviluppo per l'archiviazione dei dati. Creare la directory se non esiste. La shell mongoDB non crea nuove directory:
- macOS/Linux: ad esempio.
/usr/local/var/mongodb
- Windows: ad esempio.
C:\\BooksData
- macOS/Linux: ad esempio.
Nella shell dei comandi del sistema operativo (non nella shell mongoDB) usare il comando seguente per connettersi a MongoDB sulla porta predefinita 27017. Sostituire
<data_directory_path>
con la directory scelta nel passaggio precedente.mongod --dbpath <data_directory_path>
Usare la shell MongoDB installata in precedenza nei passaggi seguenti per creare un database, creare raccolte e archiviare documenti. Per altre informazioni sui comandi della shell mongoDB, vedere mongosh
.
Aprire un'istanza della shell dei comandi mongoDB avviando
mongosh.exe
.Nella shell dei comandi connettersi al database di test predefinito eseguendo il comando seguente:
mongosh
Eseguire il comando seguente nella shell dei comandi:
use BookStore
Se non esiste già, viene creato un database denominato BookStore . Se il database esiste, la connessione viene aperta per le transazioni.
Creare una raccolta
Books
tramite il comando seguente:db.createCollection('Books')
Viene visualizzato il risultato seguente:
{ "ok" : 1 }
Definire uno schema per la raccolta
Books
e inserire due documenti usando il comando seguente: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" }])
Viene visualizzato un risultato simile al seguente:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Nota
I
ObjectId
valori visualizzati nel risultato precedente non corrispondono a quelli visualizzati nella shell dei comandi.Visualizzare i documenti nel database usando il comando seguente:
db.Books.find().pretty()
Viene visualizzato un risultato simile al seguente:
{ "_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" }
Lo schema aggiunge una proprietà
_id
generata automaticamente di tipoObjectId
per ogni documento.
Creare il progetto per l'API Web ASP.NET Core
Passare a File>Nuovo>Progetto.
Selezionare il tipo di progetto API Web core ASP.NET e selezionare Avanti.
Assegnare al progetto il nome BookStoreApi e selezionare Avanti.
Selezionare il framework .NET 8.0 (supporto a lungo termine) e selezionare Crea.
Nella finestra Console di Gestione pacchetti passare alla radice del progetto. Eseguire il comando seguente per installare il driver .NET per MongoDB:
Install-Package MongoDB.Driver
Aggiungere un modello di entità
Aggiungere una directory Models alla radice del progetto.
Aggiungere una classe
Book
alla directory Models con il codice seguente: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!; }
Nella classe precedente la
Id
proprietà è:- Obbligatorio per eseguire il mapping dell'oggetto Common Language Runtime (CLR) all'insieme MongoDB.
- Annotato con
[BsonId]
per impostare questa proprietà sulla chiave primaria del documento. - Annotato con
[BsonRepresentation(BsonType.ObjectId)]
per consentire il passaggio del parametro come tipostring
invece di una struttura ObjectId . Mongo gestisce la conversione dastring
aObjectId
.
La
BookName
proprietà viene annotata con l'attributo[BsonElement]
. Il valore dell'attributoName
rappresenta il nome della proprietà nella raccolta MongoDB.
Aggiungere un modello di configurazione
Aggiungere i valori di configurazione del database seguenti a
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Aggiungere una classe
BookStoreDatabaseSettings
alla directory Models con il codice seguente:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
La classe precedente
BookStoreDatabaseSettings
viene usata per archiviare iappsettings.json
valori delle proprietà delBookStoreDatabase
file. I nomi delle proprietà JSON e C# sono identici per semplificare il processo di mapping.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
Nel codice precedente, l'istanza di configurazione a cui viene associata la
appsettings.json
sezione delBookStoreDatabase
file viene registrata nel contenitore Inserimento dipendenze . Ad esempio, laBookStoreDatabaseSettings
proprietà dell'oggettoConnectionString
viene popolata con laBookStoreDatabase:ConnectionString
proprietà inappsettings.json
.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBookStoreDatabaseSettings
riferimento:using BookStoreApi.Models;
Aggiungere un servizio di operazioni CRUD
Aggiungere una directory Services alla radice del progetto.
Aggiungere una classe
BooksService
alla directory Services con il codice seguente: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); }
Nel codice precedente, un'istanza
BookStoreDatabaseSettings
viene recuperata dall'inserimento delle dipendenze tramite l'inserimento del costruttore. Questa tecnica consente di accedere ai valori diappsettings.json
configurazione aggiunti nella sezione Aggiungere un modello di configurazione.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
Nel codice precedente la classe
BooksService
è registrata con l'inserimento di dipendenze per supportare l'inserimento del costruttore nelle classi che la utilizzano. La durata del servizio singleton è più appropriata perchéBooksService
assume una dipendenza diretta aMongoClient
. In base alle linee guida per il riutilizzo di Mongo Client ufficiali,MongoClient
deve essere registrato nell'inserimento di dipendenze con una durata del servizio singleton.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBooksService
riferimento:using BookStoreApi.Services;
La BooksService
classe usa i membri seguenti MongoDB.Driver
per eseguire operazioni CRUD sul database:
MongoClient: legge l'istanza del server per l'esecuzione di operazioni di database. Il costruttore di questa classe viene fornito nel stringa di connessione 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: rappresenta il database Mongo per l'esecuzione delle operazioni. Questa esercitazione usa il metodo getCollection<TDocument>(collection) generico sull'interfaccia per ottenere l'accesso ai dati in una raccolta specifica. Eseguire operazioni CRUD sulla raccolta dopo la chiamata di questo metodo. Nella chiamata del metodo
GetCollection<TDocument>(collection)
:-
collection
rappresenta il nome della raccolta. -
TDocument
rappresenta il tipo di oggetto CLR archiviato nella raccolta.
-
GetCollection<TDocument>(collection)
restituisce un oggetto MongoCollection che rappresenta la raccolta. In questa esercitazione, vengono richiamati i metodi seguenti sulla raccolta:
- DeleteOneAsync: elimina un singolo documento corrispondente ai criteri di ricerca specificati.
- Trova<TDocument>: restituisce tutti i documenti nella raccolta che corrispondono ai criteri di ricerca specificati.
- InsertOneAsync: inserisce l'oggetto fornito come nuovo documento nell'insieme.
- ReplaceOneAsync: sostituisce il singolo documento corrispondente ai criteri di ricerca specificati con l'oggetto specificato.
Aggiungere un controller
Aggiungere una classe BooksController
alla directory Controllers con il codice seguente:
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();
}
}
Il controller dell'API Web precedente:
- Usa la
BooksService
classe per eseguire operazioni CRUD. - Contiene metodi di azione per supportare le richieste HTTP GET, POST, PUT e DELETE.
- Chiama CreatedAtAction nel metodo dell'azione
Create
per restituire una risposta HTTP 201. Il codice di stato 201 è la risposta standard per un metodo HTTP POST che crea una nuova risorsa nel server.CreatedAtAction
aggiunge anche un'intestazioneLocation
alla risposta. L'intestazioneLocation
specifica l'URI del libro appena creato.
Testare l'API Web
Compilare ed eseguire l'app.
Passare a
https://localhost:<port>/api/books
, dove<port>
è il numero di porta assegnato automaticamente per l'app, per testare il metodo di azione senzaGet
parametri del controller, selezionare Prova esegui>. Viene visualizzata una risposta JSON simile alla seguente:[ { "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" } ]
Passare a
https://localhost:<port>/api/books/{id here}
per testare il metodo dell'azioneGet
in overload del controller. Viene visualizzata una risposta JSON simile alla seguente:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Configurare le opzioni di serializzazione JSON
Esistono due dettagli da modificare per le risposte JSON restituite nella sezione Testare l'API Web:
- La notazione a cammello predefinita per i nomi di proprietà deve essere modificata in modo da adottare la convenzione Pascal dei nomi di proprietà dell'oggetto CLR.
- La proprietà
bookName
deve essere restituita comeName
.
Per soddisfare i requisiti precedenti, apportare le modifiche seguenti:
In
Program.cs
concatenare il codice evidenziato seguente alla chiamata del metodoAddControllers
: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);
Con la modifica precedente, i nomi delle proprietà nella risposta JSON serializzata dell'API Web corrispondono ai nomi di proprietà corrispondenti nel tipo di oggetto CLR. Ad esempio, la
Book
proprietà dellaAuthor
classe serializza comeAuthor
anzichéauthor
.In
Models/Book.cs
annotare laBookName
proprietà con l'attributo[JsonPropertyName]
:[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
Il valore
[JsonPropertyName]
dell'attributoName
rappresenta il nome della proprietà nella risposta JSON serializzata dell'API Web.Aggiungere il codice seguente all'inizio di
Models/Book.cs
per risolvere il riferimento all'attributo[JsonProperty]
:using System.Text.Json.Serialization;
Ripetere i passaggi definiti nella sezione Testare l'API Web. Si noti la differenza nei nomi di proprietà JSON.
Aggiungere il supporto per l'autenticazione a un'API Web
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende Identity Server abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Importante
Duende Software potrebbe richiedere il pagamento di una tariffa di licenza per l'uso in produzione di Duende Identity Server. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.
Per altre informazioni, vedere la documentazione di Duende Server (sito Web duende Identity Software).
Risorse aggiuntive
Questa esercitazione crea un'API Web che esegue operazioni Create, Read, Update e Delete (CRUD) in un database NoSQL mongoDB .
In questa esercitazione apprenderai a:
- Configurare MongoDB
- Creare un database MongoDB
- Definire una raccolta e uno schema MongoDB
- Eseguire operazioni CRUD di MongoDB da un'API Web
- Personalizzare la serializzazione JSON
Prerequisiti
Visual Studio 2022 con il carico di lavoro Sviluppo ASP.NET e Web.
Configurare MongoDB
Abilitare l'accesso a MongoDB e Mongo DB Shell da qualsiasi punto del computer di sviluppo:
In Windows MongoDB viene installato in C:\Programmi\MongoDB per impostazione predefinita. Aggiungere C:\Programmi\MongoDB\Server\<version_number>\bin alla
PATH
variabile di ambiente.Scaricare la shell mongoDB e scegliere una directory in cui estrarla. Aggiungere il percorso risultante per
mongosh.exe
allaPATH
variabile di ambiente.Scegliere una directory nel computer di sviluppo per l'archiviazione dei dati. Ad esempio, C:\BooksData in Windows. Creare la directory se non esiste. La shell mongo non consente di creare nuove directory.
Nella shell dei comandi del sistema operativo (non nella shell mongoDB) usare il comando seguente per connettersi a MongoDB sulla porta predefinita 27017. Sostituire
<data_directory_path>
con la directory scelta nel passaggio precedente.mongod --dbpath <data_directory_path>
Usare la shell MongoDB installata in precedenza nei passaggi seguenti per creare un database, creare raccolte e archiviare documenti. Per altre informazioni sui comandi della shell mongoDB, vedere mongosh
.
Aprire un'istanza della shell dei comandi mongoDB avviando
mongosh.exe
.Nella shell dei comandi connettersi al database di test predefinito eseguendo il comando seguente:
mongosh
Eseguire il comando seguente nella shell dei comandi:
use BookStore
Se non esiste già, viene creato un database denominato BookStore . Se il database esiste, la connessione viene aperta per le transazioni.
Creare una raccolta
Books
tramite il comando seguente:db.createCollection('Books')
Viene visualizzato il risultato seguente:
{ "ok" : 1 }
Definire uno schema per la raccolta
Books
e inserire due documenti usando il comando seguente: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" }])
Viene visualizzato un risultato simile al seguente:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Nota
I
ObjectId
valori visualizzati nel risultato precedente non corrispondono a quelli visualizzati nella shell dei comandi.Visualizzare i documenti nel database usando il comando seguente:
db.Books.find().pretty()
Viene visualizzato un risultato simile al seguente:
{ "_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" }
Lo schema aggiunge una proprietà
_id
generata automaticamente di tipoObjectId
per ogni documento.
Creare il progetto per l'API Web ASP.NET Core
Passare a File>Nuovo>Progetto.
Selezionare il tipo di progetto API Web core ASP.NET e selezionare Avanti.
Assegnare al progetto il nome BookStoreApi e selezionare Avanti.
Selezionare il framework .NET 7.0 (Supporto termini standard) e selezionare Crea.
Nel menu Strumenti selezionare Gestione pacchetti NuGet>Console di Gestione pacchetti.
Nella finestra Console di Gestione pacchetti passare alla radice del progetto. Eseguire il comando seguente per installare il driver .NET per MongoDB:
Install-Package MongoDB.Driver
Aggiungere un modello di entità
Aggiungere una directory Models alla radice del progetto.
Aggiungere una classe
Book
alla directory Models con il codice seguente: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!; }
Nella classe precedente la
Id
proprietà è:- Obbligatorio per eseguire il mapping dell'oggetto Common Language Runtime (CLR) all'insieme MongoDB.
- Annotato con
[BsonId]
per impostare questa proprietà sulla chiave primaria del documento. - Annotato con
[BsonRepresentation(BsonType.ObjectId)]
per consentire il passaggio del parametro come tipostring
invece di una struttura ObjectId . Mongo gestisce la conversione dastring
aObjectId
.
La
BookName
proprietà viene annotata con l'attributo[BsonElement]
. Il valore dell'attributoName
rappresenta il nome della proprietà nella raccolta MongoDB.
Aggiungere un modello di configurazione
Aggiungere i valori di configurazione del database seguenti a
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Aggiungere una classe
BookStoreDatabaseSettings
alla directory Models con il codice seguente:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
La classe precedente
BookStoreDatabaseSettings
viene usata per archiviare iappsettings.json
valori delle proprietà delBookStoreDatabase
file. I nomi delle proprietà JSON e C# sono identici per semplificare il processo di mapping.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
Nel codice precedente, l'istanza di configurazione a cui viene associata la
appsettings.json
sezione delBookStoreDatabase
file viene registrata nel contenitore Inserimento dipendenze . Ad esempio, laBookStoreDatabaseSettings
proprietà dell'oggettoConnectionString
viene popolata con laBookStoreDatabase:ConnectionString
proprietà inappsettings.json
.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBookStoreDatabaseSettings
riferimento:using BookStoreApi.Models;
Aggiungere un servizio di operazioni CRUD
Aggiungere una directory Services alla radice del progetto.
Aggiungere una classe
BooksService
alla directory Services con il codice seguente: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); }
Nel codice precedente, un'istanza
BookStoreDatabaseSettings
viene recuperata dall'inserimento delle dipendenze tramite l'inserimento del costruttore. Questa tecnica consente di accedere ai valori diappsettings.json
configurazione aggiunti nella sezione Aggiungere un modello di configurazione.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
Nel codice precedente la classe
BooksService
è registrata con l'inserimento di dipendenze per supportare l'inserimento del costruttore nelle classi che la utilizzano. La durata del servizio singleton è più appropriata perchéBooksService
assume una dipendenza diretta aMongoClient
. In base alle linee guida per il riutilizzo di Mongo Client ufficiali,MongoClient
deve essere registrato nell'inserimento di dipendenze con una durata del servizio singleton.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBooksService
riferimento:using BookStoreApi.Services;
La BooksService
classe usa i membri seguenti MongoDB.Driver
per eseguire operazioni CRUD sul database:
MongoClient: legge l'istanza del server per l'esecuzione di operazioni di database. Al costruttore di questa classe viene passata la stringa di connessione 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: rappresenta il database Mongo per l'esecuzione delle operazioni. Questa esercitazione usa il metodo getCollection<TDocument>(collection) generico sull'interfaccia per ottenere l'accesso ai dati in una raccolta specifica. Eseguire operazioni CRUD sulla raccolta dopo la chiamata di questo metodo. Nella chiamata del metodo
GetCollection<TDocument>(collection)
:-
collection
rappresenta il nome della raccolta. -
TDocument
rappresenta il tipo di oggetto CLR archiviato nella raccolta.
-
GetCollection<TDocument>(collection)
restituisce un oggetto MongoCollection che rappresenta la raccolta. In questa esercitazione, vengono richiamati i metodi seguenti sulla raccolta:
- DeleteOneAsync: elimina un singolo documento corrispondente ai criteri di ricerca specificati.
- Trova<TDocument>: restituisce tutti i documenti nella raccolta che corrispondono ai criteri di ricerca specificati.
- InsertOneAsync: inserisce l'oggetto fornito come nuovo documento nell'insieme.
- ReplaceOneAsync: sostituisce il singolo documento corrispondente ai criteri di ricerca specificati con l'oggetto specificato.
Aggiungere un controller
Aggiungere una classe BooksController
alla directory Controllers con il codice seguente:
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();
}
}
Il controller dell'API Web precedente:
- Usa la
BooksService
classe per eseguire operazioni CRUD. - Contiene metodi di azione per supportare le richieste HTTP GET, POST, PUT e DELETE.
- Chiama CreatedAtAction nel metodo dell'azione
Create
per restituire una risposta HTTP 201. Il codice di stato 201 è la risposta standard per un metodo HTTP POST che crea una nuova risorsa nel server.CreatedAtAction
aggiunge anche un'intestazioneLocation
alla risposta. L'intestazioneLocation
specifica l'URI del libro appena creato.
Testare l'API Web
Compilare ed eseguire l'app.
Passare a
https://localhost:<port>/api/books
, dove<port>
è il numero di porta assegnato automaticamente per l'app, per testare il metodo di azione senzaGet
parametri del controller. Viene visualizzata una risposta JSON simile alla seguente:[ { "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" } ]
Passare a
https://localhost:<port>/api/books/{id here}
per testare il metodo dell'azioneGet
in overload del controller. Viene visualizzata una risposta JSON simile alla seguente:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Configurare le opzioni di serializzazione JSON
Esistono due dettagli da modificare per le risposte JSON restituite nella sezione Testare l'API Web:
- La notazione a cammello predefinita per i nomi di proprietà deve essere modificata in modo da adottare la convenzione Pascal dei nomi di proprietà dell'oggetto CLR.
- La proprietà
bookName
deve essere restituita comeName
.
Per soddisfare i requisiti precedenti, apportare le modifiche seguenti:
In
Program.cs
concatenare il codice evidenziato seguente alla chiamata del metodoAddControllers
: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);
Con la modifica precedente, i nomi delle proprietà nella risposta JSON serializzata dell'API Web corrispondono ai nomi di proprietà corrispondenti nel tipo di oggetto CLR. Ad esempio, la
Book
proprietà dellaAuthor
classe serializza comeAuthor
anzichéauthor
.In
Models/Book.cs
annotare laBookName
proprietà con l'attributo[JsonPropertyName]
:[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
Il valore
[JsonPropertyName]
dell'attributoName
rappresenta il nome della proprietà nella risposta JSON serializzata dell'API Web.Aggiungere il codice seguente all'inizio di
Models/Book.cs
per risolvere il riferimento all'attributo[JsonProperty]
:using System.Text.Json.Serialization;
Ripetere i passaggi definiti nella sezione Testare l'API Web. Si noti la differenza nei nomi di proprietà JSON.
Aggiungere il supporto per l'autenticazione a un'API Web
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende Identity Server abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Importante
Duende Software potrebbe richiedere il pagamento di una tariffa di licenza per l'uso in produzione di Duende Identity Server. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.
Per altre informazioni, vedere la documentazione di Duende Server (sito Web duende Identity Software).
Risorse aggiuntive
Questa esercitazione crea un'API Web che esegue operazioni Create, Read, Update e Delete (CRUD) in un database NoSQL mongoDB .
In questa esercitazione apprenderai a:
- Configurare MongoDB
- Creare un database MongoDB
- Definire una raccolta e uno schema MongoDB
- Eseguire operazioni CRUD di MongoDB da un'API Web
- Personalizzare la serializzazione JSON
Prerequisiti
- Visual Studio 2022 con il carico di lavoro Sviluppo ASP.NET e Web.
- .NET 6.0 SDK
Configurare MongoDB
Abilitare l'accesso a MongoDB e Mongo DB Shell da qualsiasi punto del computer di sviluppo:
In Windows MongoDB viene installato in C:\Programmi\MongoDB per impostazione predefinita. Aggiungere C:\Programmi\MongoDB\Server\<version_number>\bin alla
PATH
variabile di ambiente.Scaricare la shell mongoDB e scegliere una directory in cui estrarla. Aggiungere il percorso risultante per
mongosh.exe
allaPATH
variabile di ambiente.Scegliere una directory nel computer di sviluppo per l'archiviazione dei dati. Ad esempio, C:\BooksData in Windows. Creare la directory se non esiste. La shell mongo non consente di creare nuove directory.
Nella shell dei comandi del sistema operativo (non nella shell mongoDB) usare il comando seguente per connettersi a MongoDB sulla porta predefinita 27017. Sostituire
<data_directory_path>
con la directory scelta nel passaggio precedente.mongod --dbpath <data_directory_path>
Usare la shell MongoDB installata in precedenza nei passaggi seguenti per creare un database, creare raccolte e archiviare documenti. Per altre informazioni sui comandi della shell mongoDB, vedere mongosh
.
Aprire un'istanza della shell dei comandi mongoDB avviando
mongosh.exe
.Nella shell dei comandi connettersi al database di test predefinito eseguendo il comando seguente:
mongosh
Eseguire il comando seguente nella shell dei comandi:
use BookStore
Se non esiste già, viene creato un database denominato BookStore . Se il database esiste, la connessione viene aperta per le transazioni.
Creare una raccolta
Books
tramite il comando seguente:db.createCollection('Books')
Viene visualizzato il risultato seguente:
{ "ok" : 1 }
Definire uno schema per la raccolta
Books
e inserire due documenti usando il comando seguente: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" }])
Viene visualizzato un risultato simile al seguente:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61a6058e6c43f32854e51f51"), ObjectId("61a6058e6c43f32854e51f52") ] }
Nota
I
ObjectId
valori visualizzati nel risultato precedente non corrispondono a quelli visualizzati nella shell dei comandi.Visualizzare i documenti nel database usando il comando seguente:
db.Books.find().pretty()
Viene visualizzato un risultato simile al seguente:
{ "_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" }
Lo schema aggiunge una proprietà
_id
generata automaticamente di tipoObjectId
per ogni documento.
Creare il progetto per l'API Web ASP.NET Core
Passare a File>Nuovo>Progetto.
Selezionare il tipo di progetto API Web core ASP.NET e selezionare Avanti.
Assegnare al progetto il nome BookStoreApi e selezionare Avanti.
Selezionare il framework .NET 6.0 (supporto a lungo termine) e selezionare Crea.
Nella finestra Console di Gestione pacchetti passare alla radice del progetto. Eseguire il comando seguente per installare il driver .NET per MongoDB:
Install-Package MongoDB.Driver
Aggiungere un modello di entità
Aggiungere una directory Models alla radice del progetto.
Aggiungere una classe
Book
alla directory Models con il codice seguente: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!; }
Nella classe precedente la
Id
proprietà è:- Obbligatorio per eseguire il mapping dell'oggetto Common Language Runtime (CLR) all'insieme MongoDB.
- Annotato con
[BsonId]
per impostare questa proprietà sulla chiave primaria del documento. - Annotato con
[BsonRepresentation(BsonType.ObjectId)]
per consentire il passaggio del parametro come tipostring
invece di una struttura ObjectId . Mongo gestisce la conversione dastring
aObjectId
.
La
BookName
proprietà viene annotata con l'attributo[BsonElement]
. Il valore dell'attributoName
rappresenta il nome della proprietà nella raccolta MongoDB.
Aggiungere un modello di configurazione
Aggiungere i valori di configurazione del database seguenti a
appsettings.json
:{ "BookStoreDatabase": { "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookStore", "BooksCollectionName": "Books" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Aggiungere una classe
BookStoreDatabaseSettings
alla directory Models con il codice seguente:namespace BookStoreApi.Models; public class BookStoreDatabaseSettings { public string ConnectionString { get; set; } = null!; public string DatabaseName { get; set; } = null!; public string BooksCollectionName { get; set; } = null!; }
La classe precedente
BookStoreDatabaseSettings
viene usata per archiviare iappsettings.json
valori delle proprietà delBookStoreDatabase
file. I nomi delle proprietà JSON e C# sono identici per semplificare il processo di mapping.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase"));
Nel codice precedente, l'istanza di configurazione a cui viene associata la
appsettings.json
sezione delBookStoreDatabase
file viene registrata nel contenitore Inserimento dipendenze . Ad esempio, laBookStoreDatabaseSettings
proprietà dell'oggettoConnectionString
viene popolata con laBookStoreDatabase:ConnectionString
proprietà inappsettings.json
.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBookStoreDatabaseSettings
riferimento:using BookStoreApi.Models;
Aggiungere un servizio di operazioni CRUD
Aggiungere una directory Services alla radice del progetto.
Aggiungere una classe
BooksService
alla directory Services con il codice seguente: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); }
Nel codice precedente, un'istanza
BookStoreDatabaseSettings
viene recuperata dall'inserimento delle dipendenze tramite l'inserimento del costruttore. Questa tecnica consente di accedere ai valori diappsettings.json
configurazione aggiunti nella sezione Aggiungere un modello di configurazione.Aggiungere il codice evidenziato seguente a
Program.cs
:var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.Configure<BookStoreDatabaseSettings>( builder.Configuration.GetSection("BookStoreDatabase")); builder.Services.AddSingleton<BooksService>();
Nel codice precedente la classe
BooksService
è registrata con l'inserimento di dipendenze per supportare l'inserimento del costruttore nelle classi che la utilizzano. La durata del servizio singleton è più appropriata perchéBooksService
assume una dipendenza diretta aMongoClient
. In base alle linee guida per il riutilizzo di Mongo Client ufficiali,MongoClient
deve essere registrato nell'inserimento di dipendenze con una durata del servizio singleton.Aggiungere il codice seguente all'inizio di
Program.cs
per risolvere ilBooksService
riferimento:using BookStoreApi.Services;
La BooksService
classe usa i membri seguenti MongoDB.Driver
per eseguire operazioni CRUD sul database:
MongoClient: legge l'istanza del server per l'esecuzione di operazioni di database. Al costruttore di questa classe viene passata la stringa di connessione 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: rappresenta il database Mongo per l'esecuzione delle operazioni. Questa esercitazione usa il metodo getCollection<TDocument>(collection) generico sull'interfaccia per ottenere l'accesso ai dati in una raccolta specifica. Eseguire operazioni CRUD sulla raccolta dopo la chiamata di questo metodo. Nella chiamata del metodo
GetCollection<TDocument>(collection)
:-
collection
rappresenta il nome della raccolta. -
TDocument
rappresenta il tipo di oggetto CLR archiviato nella raccolta.
-
GetCollection<TDocument>(collection)
restituisce un oggetto MongoCollection che rappresenta la raccolta. In questa esercitazione, vengono richiamati i metodi seguenti sulla raccolta:
- DeleteOneAsync: elimina un singolo documento corrispondente ai criteri di ricerca specificati.
- Trova<TDocument>: restituisce tutti i documenti nella raccolta che corrispondono ai criteri di ricerca specificati.
- InsertOneAsync: inserisce l'oggetto fornito come nuovo documento nell'insieme.
- ReplaceOneAsync: sostituisce il singolo documento corrispondente ai criteri di ricerca specificati con l'oggetto specificato.
Aggiungere un controller
Aggiungere una classe BooksController
alla directory Controllers con il codice seguente:
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();
}
}
Il controller dell'API Web precedente:
- Usa la
BooksService
classe per eseguire operazioni CRUD. - Contiene metodi di azione per supportare le richieste HTTP GET, POST, PUT e DELETE.
- Chiama CreatedAtAction nel metodo dell'azione
Create
per restituire una risposta HTTP 201. Il codice di stato 201 è la risposta standard per un metodo HTTP POST che crea una nuova risorsa nel server.CreatedAtAction
aggiunge anche un'intestazioneLocation
alla risposta. L'intestazioneLocation
specifica l'URI del libro appena creato.
Testare l'API Web
Compilare ed eseguire l'app.
Passare a
https://localhost:<port>/api/books
, dove<port>
è il numero di porta assegnato automaticamente per l'app, per testare il metodo di azione senzaGet
parametri del controller. Viene visualizzata una risposta JSON simile alla seguente:[ { "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" } ]
Passare a
https://localhost:<port>/api/books/{id here}
per testare il metodo dell'azioneGet
in overload del controller. Viene visualizzata una risposta JSON simile alla seguente:{ "id": "61a6058e6c43f32854e51f52", "bookName": "Clean Code", "price": 43.15, "category": "Computers", "author": "Robert C. Martin" }
Configurare le opzioni di serializzazione JSON
Esistono due dettagli da modificare per le risposte JSON restituite nella sezione Testare l'API Web:
- La notazione a cammello predefinita per i nomi di proprietà deve essere modificata in modo da adottare la convenzione Pascal dei nomi di proprietà dell'oggetto CLR.
- La proprietà
bookName
deve essere restituita comeName
.
Per soddisfare i requisiti precedenti, apportare le modifiche seguenti:
In
Program.cs
concatenare il codice evidenziato seguente alla chiamata del metodoAddControllers
: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);
Con la modifica precedente, i nomi delle proprietà nella risposta JSON serializzata dell'API Web corrispondono ai nomi di proprietà corrispondenti nel tipo di oggetto CLR. Ad esempio, la
Book
proprietà dellaAuthor
classe serializza comeAuthor
anzichéauthor
.In
Models/Book.cs
annotare laBookName
proprietà con l'attributo[JsonPropertyName]
:[BsonElement("Name")] [JsonPropertyName("Name")] public string BookName { get; set; } = null!;
Il valore
[JsonPropertyName]
dell'attributoName
rappresenta il nome della proprietà nella risposta JSON serializzata dell'API Web.Aggiungere il codice seguente all'inizio di
Models/Book.cs
per risolvere il riferimento all'attributo[JsonProperty]
:using System.Text.Json.Serialization;
Ripetere i passaggi definiti nella sezione Testare l'API Web. Si noti la differenza nei nomi di proprietà JSON.
Aggiungere il supporto per l'autenticazione a un'API Web
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende Identity Server abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Importante
Duende Software potrebbe richiedere il pagamento di una tariffa di licenza per l'uso in produzione di Duende Identity Server. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.
Per altre informazioni, vedere la documentazione di Duende Server (sito Web duende Identity Software).
Risorse aggiuntive
Questa esercitazione crea un'API Web che esegue operazioni Create, Read, Update e Delete (CRUD) in un database NoSQL mongoDB .
In questa esercitazione apprenderai a:
- Configurare MongoDB
- Creare un database MongoDB
- Definire una raccolta e uno schema MongoDB
- Eseguire operazioni CRUD di MongoDB da un'API Web
- Personalizzare la serializzazione JSON
Visualizzare o scaricare il codice di esempio (procedura per il download)
Prerequisiti
- .NET Core SDK 3.0 o versione successiva
- Visual Studio 2019 con il carico di lavoro Sviluppo ASP.NET e Web
- MongoDB
Configurare MongoDB
Se si usa Windows, MongoDB è installato in C:\Programmi\MongoDB per impostazione predefinita. Aggiungere C:\Programmi\MongoDB\Server\<version_number>\bin alla Path
variabile di ambiente. Questa modifica consente l'accesso MongoDB da qualsiasi posizione nel computer di sviluppo.
Usare la shell mongo nelle procedure seguenti per creare un database, creare le raccolte e archiviare i documenti. Per altre informazioni sui comandi della shell mongo, vedere Working with the mongo Shell (Utilizzo della shell mongo).
Scegliere una directory nel computer di sviluppo per archiviare i dati. Ad esempio, C:\BooksData in Windows. Creare la directory se non esiste. La shell mongo non consente di creare nuove directory.
Aprire una shell dei comandi. Eseguire il comando seguente per connettersi a MongoDB sulla porta predefinita 27017. Ricordare di sostituire
<data_directory_path>
con la directory scelta nel passaggio precedente.mongod --dbpath <data_directory_path>
Aprire un'altra istanza della shell dei comandi. Connettersi al database di test predefinito eseguendo il comando seguente:
mongo
Eseguire il comando seguente in una shell dei comandi:
use BookstoreDb
Se non esiste già, viene creato un database denominato BookstoreDb . Se il database esiste, la connessione viene aperta per le transazioni.
Creare una raccolta
Books
tramite il comando seguente:db.createCollection('Books')
Viene visualizzato il risultato seguente:
{ "ok" : 1 }
Definire uno schema per la raccolta
Books
e inserire due documenti usando il comando seguente: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'}])
Viene visualizzato il risultato seguente:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("5bfd996f7b8e48dc15ff215d"), ObjectId("5bfd996f7b8e48dc15ff215e") ] }
Nota
L'ID illustrato in questo articolo non corrisponde agli ID quando si esegue questo campione.
Visualizzare i documenti nel database usando il comando seguente:
db.Books.find({}).pretty()
Viene visualizzato il risultato seguente:
{ "_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" }
Lo schema aggiunge una proprietà
_id
generata automaticamente di tipoObjectId
per ogni documento.
Il database è pronto. È possibile iniziare a creare l'API Web ASP.NET Core.
Creare il progetto per l'API Web ASP.NET Core
Passare a File>Nuovo>Progetto.
Selezionare il tipo di progetto Applicazione Web ASP.NET Core e selezionare Avanti.
Assegnare al progetto il nome BooksApi e selezionare Crea.
Selezionare il framework di destinazione .NET Core e ASP.NET Core 3.0. Selezionare il modello di progetto API e scegliere Crea.
Visitare la raccolta NuGet: MongoDB.Driver per determinare la versione stabile più recente del driver .NET per MongoDB. Nella finestra Console di Gestione pacchetti passare alla radice del progetto. Eseguire il comando seguente per installare il driver .NET per MongoDB:
Install-Package MongoDB.Driver -Version {VERSION}
Aggiungere un modello di entità
Aggiungere una directory Models alla radice del progetto.
Aggiungere una classe
Book
alla directory Models con il codice seguente: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; } } }
Nella classe precedente la
Id
proprietà è:- Obbligatorio per eseguire il mapping dell'oggetto Common Language Runtime (CLR) all'insieme MongoDB.
- Annotato con
[BsonId]
per impostare questa proprietà sulla chiave primaria del documento. - Annotato con
[BsonRepresentation(BsonType.ObjectId)]
per consentire il passaggio del parametro come tipostring
invece di una struttura ObjectId . Mongo gestisce la conversione dastring
aObjectId
.
La
BookName
proprietà viene annotata con l'attributo[BsonElement]
. Il valore dell'attributoName
rappresenta il nome della proprietà nella raccolta MongoDB.
Aggiungere un modello di configurazione
Aggiungere i valori di configurazione del database seguenti a
appsettings.json
:{ "BookstoreDatabaseSettings": { "BooksCollectionName": "Books", "ConnectionString": "mongodb://localhost:27017", "DatabaseName": "BookstoreDb" }, "Logging": { "IncludeScopes": false, "Debug": { "LogLevel": { "Default": "Warning" } }, "Console": { "LogLevel": { "Default": "Warning" } } } }
Aggiungere un
BookstoreDatabaseSettings.cs
file alla directory Models con il codice seguente: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; } } }
La classe precedente
BookstoreDatabaseSettings
viene usata per archiviare iappsettings.json
valori delle proprietà delBookstoreDatabaseSettings
file. I nomi delle proprietà JSON e C# sono identici per semplificare il processo di mapping.Aggiungere il codice evidenziato seguente a
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(); }
Nel codice precedente:
- L'istanza di configurazione a cui viene associata la
appsettings.json
sezione delBookstoreDatabaseSettings
file viene registrata nel contenitore inserimento delle dipendenze . Ad esempio, la proprietà di unBookstoreDatabaseSettings
oggetto viene popolata con laConnectionString
proprietà inBookstoreDatabaseSettings:ConnectionString
.appsettings.json
- L'interfaccia
IBookstoreDatabaseSettings
è registrata nell'inserimento di dipendenze con una durata del servizio singleton. Quando avviene l'inserimento, l'istanza dell'interfaccia restituisce un oggettoBookstoreDatabaseSettings
.
- L'istanza di configurazione a cui viene associata la
Aggiungere il codice seguente all'inizio di
Startup.cs
per risolvere iBookstoreDatabaseSettings
riferimenti eIBookstoreDatabaseSettings
:using BooksApi.Models;
Aggiungere un servizio di operazioni CRUD
Aggiungere una directory Services alla radice del progetto.
Aggiungere una classe
BookService
alla directory Services con il codice seguente: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); } }
Nel codice precedente un'istanza di
IBookstoreDatabaseSettings
viene recuperata dall'inserimento di dipendenze tramite l'inserimento del costruttore. Questa tecnica consente di accedere ai valori diappsettings.json
configurazione aggiunti nella sezione Aggiungere un modello di configurazione.Aggiungere il codice evidenziato seguente a
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(); }
Nel codice precedente la classe
BookService
è registrata con l'inserimento di dipendenze per supportare l'inserimento del costruttore nelle classi che la utilizzano. La durata del servizio singleton è più appropriata perchéBookService
assume una dipendenza diretta aMongoClient
. In base alle linee guida per il riutilizzo di Mongo Client ufficiali,MongoClient
deve essere registrato nell'inserimento di dipendenze con una durata del servizio singleton.Aggiungere il codice seguente all'inizio di
Startup.cs
per risolvere ilBookService
riferimento:using BooksApi.Services;
La BookService
classe usa i membri seguenti MongoDB.Driver
per eseguire operazioni CRUD sul database:
MongoClient: legge l'istanza del server per l'esecuzione di operazioni di database. Al costruttore di questa classe viene passata la stringa di connessione MongoDB:
public BookService(IBookstoreDatabaseSettings settings) { var client = new MongoClient(settings.ConnectionString); var database = client.GetDatabase(settings.DatabaseName); _books = database.GetCollection<Book>(settings.BooksCollectionName); }
IMongoDatabase: rappresenta il database Mongo per l'esecuzione delle operazioni. Questa esercitazione usa il metodo getCollection<TDocument>(collection) generico sull'interfaccia per ottenere l'accesso ai dati in una raccolta specifica. Eseguire operazioni CRUD sulla raccolta dopo la chiamata di questo metodo. Nella chiamata del metodo
GetCollection<TDocument>(collection)
:-
collection
rappresenta il nome della raccolta. -
TDocument
rappresenta il tipo di oggetto CLR archiviato nella raccolta.
-
GetCollection<TDocument>(collection)
restituisce un oggetto MongoCollection che rappresenta la raccolta. In questa esercitazione, vengono richiamati i metodi seguenti sulla raccolta:
- DeleteOne: elimina un singolo documento corrispondente ai criteri di ricerca specificati.
- Trova<TDocument>: restituisce tutti i documenti nella raccolta che corrispondono ai criteri di ricerca specificati.
- InsertOne: inserisce l'oggetto fornito come nuovo documento nell'insieme.
- ReplaceOne: sostituisce il singolo documento corrispondente ai criteri di ricerca specificati con l'oggetto specificato.
Aggiungere un controller
Aggiungere una classe BooksController
alla directory Controllers con il codice seguente:
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();
}
}
}
Il controller dell'API Web precedente:
- Usa la
BookService
classe per eseguire operazioni CRUD. - Contiene metodi di azione per supportare le richieste HTTP GET, POST, PUT e DELETE.
- Chiama CreatedAtRoute nel metodo dell'azione
Create
per restituire una risposta HTTP 201. Il codice di stato 201 è la risposta standard per un metodo HTTP POST che crea una nuova risorsa nel server.CreatedAtRoute
aggiunge anche un'intestazioneLocation
alla risposta. L'intestazioneLocation
specifica l'URI del libro appena creato.
Testare l'API Web
Compilare ed eseguire l'app.
Passare a
https://localhost:<port>/api/books
per testare il metodo dell'azioneGet
senza parametri del controller. Viene visualizzata la risposta JSON seguente:[ { "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" } ]
Passare a
https://localhost:<port>/api/books/{id here}
per testare il metodo dell'azioneGet
in overload del controller. Viene visualizzata la risposta JSON seguente:{ "id":"{ID}", "bookName":"Clean Code", "price":43.15, "category":"Computers", "author":"Robert C. Martin" }
Configurare le opzioni di serializzazione JSON
Esistono due dettagli da modificare per le risposte JSON restituite nella sezione Testare l'API Web:
- La notazione a cammello predefinita per i nomi di proprietà deve essere modificata in modo da adottare la convenzione Pascal dei nomi di proprietà dell'oggetto CLR.
- La proprietà
bookName
deve essere restituita comeName
.
Per soddisfare i requisiti precedenti, apportare le modifiche seguenti:
Json.NET è stato rimosso dal framework condiviso di ASP.NET. Aggiungere un riferimento al pacchetto a
Microsoft.AspNetCore.Mvc.NewtonsoftJson
.In
Startup.ConfigureServices
concatenare il codice evidenziato seguente alla chiamata del metodoAddControllers
: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()); }
Con la modifica precedente, i nomi delle proprietà nella risposta JSON serializzata dell'API Web corrispondono ai nomi di proprietà corrispondenti nel tipo di oggetto CLR. Ad esempio, la proprietà
Book
della classeAuthor
viene serializzata comeAuthor
.In
Models/Book.cs
annotare laBookName
proprietà con l'attributo seguente[JsonProperty]
:[BsonElement("Name")] [JsonProperty("Name")] public string BookName { get; set; }
Il valore
[JsonProperty]
dell'attributoName
rappresenta il nome della proprietà nella risposta JSON serializzata dell'API Web.Aggiungere il codice seguente all'inizio di
Models/Book.cs
per risolvere il riferimento all'attributo[JsonProperty]
:using Newtonsoft.Json;
Ripetere i passaggi definiti nella sezione Testare l'API Web. Si noti la differenza nei nomi di proprietà JSON.
Aggiungere il supporto per l'autenticazione a un'API Web
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer è un prodotto di terze parti.
Duende IdentityServer è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende IdentityServer abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Per altre informazioni, vedere Panoramica di Duende IdentityServer.
Per altre informazioni su altri provider di autenticazione, vedere Opzioni di autenticazione del sistema operativo della community per ASP.NET Core
Passaggi successivi
Per altre informazioni sulla creazione di API Web ASP.NET Core, vedere le risorse seguenti: