Tutorial utilizzo di Asp.Net core API con il database MongoDB

Articolo introduttivo che fornisce una panoramica sulla creazione di un servizio web api con .Net 9 e C# per gestire il database MongoDB Community.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

In questo articolo vedremo come realizzare un’applicazione web API Asp.Net per utilizzare una fonte dati di tipo NoSQL, quale MongoDB Community.
In particolare, vedremo come realizzare servizi REST utilizzando la tecnologia Asp.Net ed il linguaggio di programmazione C#, e le relative web api per eseguire le varie operazioni CRUD.
Come database utilizzeremo MongoDB Community, il database gratuito che si può installare sul proprio pc, mentre per l’ambiente di sviluppo Visual Studio 2022 Community e versione .Net 9

Creazione del progetto


Dopo aver aperto Visual Studio 2022 Community, selezioniamo come modello di progetto, quello relativo alla voce “API WEB Asp.Net core”, il tutto come mostrato in figura 1.

Figura 1 – Il modello del progetto

Figura 1 – Il modello del progetto

Una volta selezionato il modello, selezioniamo il pulsante avanti, e nella finestra successiva impostiamo il nome, facciamo click sul pulsante “Avanti”, e nella successiva finestra, lasciamo impostato i check per “Abilita Supporto OpenAPI” e per l’opzione “Usa I Controller”, il tutto come mostrato in figura 2.

Figura 2 – Le opzioni per la creazione del progetto

Figura 2 – Le opzioni per la creazione del progetto 

Confermiamo con il pulsante “Crea”, in modo da creare il progetto.
Tramite la finestra “Nuget”, aggiungiamo nel nostro progetto il pacchetto relativo a “MongoDB.Driver”, il tutto come mostrato in figura 3.

Figura 3 – L’aggiunta del pacchetto MondoDB.Driver

Figura 3 – L’aggiunta del pacchetto MondoDB.Driver

Se non è presente nel progetto la cartella “Models”, dalla finestra di “Esplora Soluzioni”, se ne crea una nuova.
La creazione del progetto è terminata, ora non resta che scrivere il codice.

Stesura del codice


Nella finestra “Esplora soluzioni”, facciamo click sulla cartella “Models” con il tasto destro del mouse, nel menu che viene visualizzato, selezioniamo “Classe” e come nome impostiamo quello di una collection presente nel database. Nel nostro caso, avendo una collection denominata “Dati”, daremo il valore “Dati”.
La classe dati, dovrà mappare i campi della collection, quindi dobbiamo scrivere le proprietà dei vari campi della collectioni.
Nella classe, sopra ad ogni dichiarazione, aggiungiamo lo spazio dei nomi, per gestire i vari campi di tipo “MongoDB”, di seguito si riporta il frammento delle suddette operazioni.

C#
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

La classe rappresenterà la collection, di seguito la dichiarazione di classe.

C#
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace WebMongoDB.Models
{
   public class Dati
   {
       [BsonId]
       [BsonRepresentation(BsonType.ObjectId)]
       public string? Id { get; set; }
       [BsonElement("nome")]
       public string Nome { get; set; } = null!;
       [BsonElement("cognome")]
       public string Cognome { get; set; } = null!;
       [BsonElement("email")]
       public string Email { get; set; } = null!;
       [BsonElement("data_nascita")]
       public DateTime  DataNascita { get; set; } 
   }
}

Il campo Id, essendo un campo univoco, è stato impostato di tipo “ObjectID.
Aggiungiamo al file “appsettings.json”, la stringa di connessione al database, impostando anche il nome del database ed il nome della collection, di seguito la stringa di connessione.

//Connection string per il database MongoDB
"MongoDBSettings": {
  "ConnectionString": "mongodb://localhost:27017",
  "DatabaseName": "Amministrazione",
  "CollectionName": "Dati"
},

Di seguito il codice completo del file.

{
 //Connection string for MongoDB
 "MongoDBSettings": {
   "ConnectionString": "mongodb://localhost:27017",
   "DatabaseName": "Amministrazione",
   "CollectionName": "Dati"
 },
 "Logging": {
   "LogLevel": {
     "Default": "Information",
     "Microsoft.AspNetCore": "Warning"
   }
 },
 "AllowedHosts": "*"
}

Nella cartella “Models”, aggiungiamo una classe, che farà da mappatura con il file di configurazione. Si crea una classe denominata “DatiSettings”, con le proprietà riguardante i vari campi.
Di seguito si riporta il codice delle suddette operazioni.

C#
public class DatiSettings
{
   public string ConnectionString { get; set; } = null!;
   public string DatabaseName { get; set; } = null!;
   public string CollectionName { get; set; } = null!;
}


Apriamo il  file “Programm” e dopo la creazione di un oggetto Builder, aggiungiamo il codice per mappare i rifermenti nel file di setting, nella classe appena creata.

C#
using WebMongoDB.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<DatiSettings>(
   builder.Configuration.GetSection("MongoDBSettings"));

Si crea una nuova cartella, dove metteremo il file dei servizi.
La cartella si chiamerà “Servizi”, ed la classe per le varie operazioni CRUD, si chiamerà DatiServizi.
Nella classe, sopra ad ogni dichiarazione, inseriamo lo spazio dei nomi per la gestione delle classi di MongoDB.
Di seguito si riporta il frammento di codice delle suddette operazioni. 

C#
using MongoDB.Driver;
using Microsoft.Extensions.Options;

A livello di classe, si crea un oggetto privato a livello di campo, per gestire i dati della collection. 
Di seguito si riporta il frammento di codice da utilizzare a livello di campo di classe.

C#
private readonly IMongoCollection<Dati> _datiCollection;

Nel costruttore della classe, dobbiamo iniziare la collection, istanziando oggetti di tipo “MongoClient”, per la gestione del server MongoDB, un oggetto di “ImongoDAtabase”, per la gestione del database, ed infine la collection con i riferimenti che abbiamo iniziato.
Di seguito si riporta il frammento di codice delle suddette dichiarazioni.

C#
public DatiServizi(IOptions<DatiSettings> datiSettings)
{
   var mongoClient = new MongoClient(datiSettings.Value.ConnectionString);
   var mongoDatabase = mongoClient.GetDatabase(datiSettings.Value.DatabaseName);
   _datiCollection = mongoDatabase.GetCollection<Dati>(datiSettings.Value.CollectionName);
}

Terminata la parte di inizializzare la gestione della collection, non resta che creare i metodi per le varie operazioni CRUD.
Le varie operazioni utilizzando i metodi dell’oggetto “IMongoCollection” creato a livello di classe.
Di seguito si riporta il frammento di codice delle varie operazioni CRUD.

C#
//Metodo per ottenere tutti i documenti dalla collezione
public async Task<List<Dati>> GetAsync() =>
   await _datiCollection.Find(_ => true).ToListAsync();
//Metodo per ottenere un documento specifico tramite l'Id
public async Task<Dati?> GetAsync(string id) =>
   await _datiCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
//Metodo per creare un nuovo documento
public async Task CreateAsync(Dati newDati) =>
   await _datiCollection.InsertOneAsync(newDati);
//Metodo per aggiornare un documento esistente
public async Task UpdateAsync(string id, Dati updatedDati) =>
   await _datiCollection.ReplaceOneAsync(x => x.Id == id, updatedDati);
//Metodo per eliminare un documento tramite l'Id
public async Task RemoveAsync(string id) =>
   await _datiCollection.DeleteOneAsync(x => x.Id == id);

Si riporta il codice completo della classe per la gestione dei servizi per le varie operazioni CRUD, per fornire in maniera chiara tale dichiarazioni.

C#
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using WebMongoDB.Models;
namespace WebMongoDB.Servizi
{
   public class DatiServizi
   {
       private readonly IMongoCollection<Dati> _datiCollection;
       //Nel costruttore inizializzo le impostazioni di connessione a MongoDB
       public DatiServizi(IOptions<DatiSettings> datiSettings)
       {
           var mongoClient = new MongoClient(datiSettings.Value.ConnectionString);
           var mongoDatabase = mongoClient.GetDatabase(datiSettings.Value.DatabaseName);
           _datiCollection = mongoDatabase.GetCollection<Dati>(datiSettings.Value.CollectionName);
       }
       //Metodo per ottenere tutti i documenti dalla collezione
       public async Task<List<Dati>> GetAsync() =>
           await _datiCollection.Find(_ => true).ToListAsync();
       //Metodo per ottenere un documento specifico tramite l'Id
       public async Task<Dati?> GetAsync(string id) =>
           await _datiCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
       //Metodo per creare un nuovo documento
       public async Task CreateAsync(Dati newDati) =>
           await _datiCollection.InsertOneAsync(newDati);
       //Metodo per aggiornare un documento esistente
       public async Task UpdateAsync(string id, Dati updatedDati) =>
           await _datiCollection.ReplaceOneAsync(x => x.Id == id, updatedDati);
       //Metodo per eliminare un documento tramite l'Id
       public async Task RemoveAsync(string id) =>
           await _datiCollection.DeleteOneAsync(x => x.Id == id);
   }
}

Ritorniamo nel file “Program.cs” e sotto la riga di codice nel quale abbiamo gestito le impostazioni di connessione del database, aggiungiamo la classe servizi appena creata tramite il metodo “AddSingleton” .

C#
builder.Services.AddSingleton<DatiServizi>();

Di seguito si riporta tale dichiarazione.

C#
using WebMongoDB.Models;
using WebMongoDB.Servizi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<DatiSettings>(
   builder.Configuration.GetSection("MongoDBSettings"));
builder.Services.AddSingleton<DatiServizi>()

Nella cartella “Controllers”  aggiugniamo una nuova classe, denominata “DatiControllers” , tasto destro sulla cartella, e dal menu, selezioniamo la voce “Aggiungi” e nel sottomenu selezionare la voce “Classe”.
La classe deve ereditare da “ ControllerBase”, a livello di classe, si crea un oggetto per la gestione della classe dei servizi, che verrà inizializzata nel costruttore della classe.
Di seguito si riporta il frammento di codice delle suddette operazioni.

C#
using Microsoft.AspNetCore.Mvc;
using WebMongoDB.Servizi;
namespace WebMongoDB.Controllers
{
   [ApiController]
   [Route("api/[controller]")]
   public class DatiControllers : ControllerBase
   {
       private readonly DatiServizi _datiServizi;
       public DatiControllers(DatiServizi datiServizi  ) { 
           _datiServizi = datiServizi;
       }
   }
}

Nella classe, inseriamo i vari metodi per gestire le operazioni CRUD,
Di seguito si riporta il codice completo della classe.

C#
using Microsoft.AspNetCore.Mvc;
using WebMongoDB.Models;
using WebMongoDB.Servizi;
namespace WebMongoDB.Controllers
{
   [ApiController]
   [Route("api/[controller]")]
   public class DatiControllers : ControllerBase
   {
       private readonly DatiServizi _datiServizi;
       public DatiControllers(DatiServizi datiServizi  ) { 
           _datiServizi = datiServizi;
       }
       [HttpGet]
       public async Task<List<Dati>> Get() {
           return  await _datiServizi.GetAsync() ;
       }
       [HttpGet("{id:length(24)}")]
       public async Task<ActionResult<Dati>> Get(string id) {
           var dati = await _datiServizi.GetAsync(id);
           if (dati is null) {
               return NotFound();
           }
           return  dati ;
       }
       [HttpPost]
       public async Task<IActionResult> Post(Dati newDati) {
           await _datiServizi.CreateAsync(newDati);
           return CreatedAtAction(nameof(Get), new { id = newDati.Id }, newDati);
       }
       [HttpPut("{id:length(24)}")]
       public async Task<IActionResult> Update(string id, Dati updatedDati) {
           var dati = await _datiServizi.GetAsync(id);
           if (dati is null) {
               return NotFound();
           }
           updatedDati.Id = dati.Id;
           await _datiServizi.UpdateAsync(id, updatedDati);
           return NoContent();
       }   
       [HttpDelete("{id:length(24)}")]
       public async Task<IActionResult> Delete(string id) {
           var dati = await _datiServizi.GetAsync(id);
           if (dati is null) {
               return NotFound();
           }
           await _datiServizi.RemoveAsync(id);
           return NoContent();
       }   
   }
}

Ritorniamo nel file “Program.cs” ed impostiamo la gestione dei campi Json.
Di seguito si riporta il codice modificato per tale dichiarazione.

C#
using WebMongoDB.Models;
using WebMongoDB.Servizi;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<DatiSettings>(
   builder.Configuration.GetSection("MongoDBSettings"));
builder.Services.AddSingleton<DatiServizi>();
// Add services to the container.
builder.Services.AddControllers().AddJsonOptions(
       options => options.JsonSerializerOptions.PropertyNamingPolicy = null);

Impostiamo l’attributo Json per la proprietà “Nome” per la classe modelli creata in precedenza, quella denominata “Dati”.
Si riporta il codice delle seguenti dichiarazione.

C#
       [JsonPropertyName("nome")]
       [BsonElement("nome")]
       public string Nome { get; set; } = null!;

Di seguito il codice completo della classe “Dati”.

C#
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace WebMongoDB.Models
{
   public class Dati
   {
       [BsonId]
       [BsonRepresentation(BsonType.ObjectId)]
       public string? Id { get; set; }
       [JsonPropertyName("nome")]
       [BsonElement("nome")]
       public string Nome { get; set; } = null!;
       [BsonElement("cognome")]
       public string Cognome { get; set; } = null!;
       [BsonElement("email")]
       public string Email { get; set; } = null!;
       [BsonElement("data_nascita")]
       public DateTime  DataNascita { get; set; } 
   }
}

Ora non resta che eseguire le varie operazioni CRUD, per verificare la gestione delle operazioni.
Da ricordare che il modello di classe, deve avere gli stessi campi della collection, se un documento presenta un campo diverso o aggiunto, verrà generato un errore.
Il risultato sarà come mostrato in figura 4.

Figura 4 – Il test in Visual Studio 2022 Community

Figura 4 – Il test in Visual Studio 2022 Community

Conclusioni


L’articolo ha fornito al lettore una panoramica sulla realizzazione di servizi Web API utilizzando la tecnologia Asp.Net Core, con la base dati di MongoDB.  In particolare, si sono affrontati i vari aspetti per creare un servizio per gestire tutte le operazioni sui dati di questo database.