ASP.NET Core  - Web API com MongoDB


 Neste tutorial vamos recordar como usar o MongoDB desta vez no ambiente do .NET 6. Para isso vamos criar uma Web API que gerencia informações de Alunos.

O MongoDB é um banco de dados de documentos com a escalabilidade e flexibilidade que você deseja e com a consulta e indexação que você precisa. Ele armazena dados em documentos versáteis do tipo JSON. Isso significa que os campos variam de documento para documento e a estrutura de dados pode ser alterada ao longo do tempo.

O MongoDB Atlas é um banco de dados em nuvem totalmente gerenciado que lida com toda a complexidade de implantação, gerenciamento e recuperação de suas implantações no provedor de serviços de nuvem de sua escolha (Azure, AWS e GCP). (Atualmente, o MongoDB Atlas fornece 512 MB de espaço livre. )

Neste tutorial, veremos todos os passos para se conectar ao banco de dados MongoDB com uma aplicação web API  no ambiente do .NET 6.

Para instalar o MongoDB localmente acesse o site oficial e faça download da versão Community Server neste link.

Ao instalar o MongoDB você pode instalar também o MongoDb Compass que fornece uma interface visual para gerenciar o MongoDB:

Fazendo um paralelo com o modelo relacional e o MongoDB temos que entender alguns conceitos importantes:

Então podemos montar a seguinte tabela de equivalência entre o MongoDB e os RDBMS:

Banco de Dados Relacional MongoDB
Table Collection
Row Document
Column Field
Join Embedding
Schema -

Vale lembrar que no MongoDB não temos o conceito de Schema nem de Join, neste último ao invés usamos o que se chama embedding o que significa que as entidades estão contidas uma nas outras.

Primeiro vamos criar uma API que expõe endpoints para gerenciar informações de Alunos usando um banco de dados MongoDB instalado localmente e a seguir veremos como podemos poupar nosso ambiente da instalação do MongoDb usando o Docker.

Recursos usados:

Criando o projeto Web API

Crie um novo projeto no VS 2022 usando o template ASP.NET Core Web API com o nome AlunosApi.

Use as configurações definidas abaixo para criar o projeto:

A seguir instale no projeto o pacote MongoDB.Driver que iremos usar para fazer a conexão com o MongoDB.

:

Crie uma pasta Models no projeto e nesta pasta crie a classe Aluno que representa o modelo de domínio.

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace AlunosApi.Models;

public class Aluno
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]

    public string? Id { get; set; }
    public string Nome { get; set; } = null!;
    public string Endereco { get; set; } = null!;
    public int Idade { get; set; } = 0;
    public string Curso { get; set; } = null!;
    public string Email  { get; set; } = null!;
}

Observe na classe Aluno definimos um campo do tipo string chamado Id que esta decorado pelo atributo [BsonId] e esta definido como sendo do tipo ObjectId que é um valor binário de 12 bytes que consiste de:

Na classe acima, a propriedade Id é:

- Usada para mapear o objeto Common Language Runtime (CLR) para a coleção do MongoDB;
- Decorado com o atributo [BsonId] para tornar esta propriedade a chave primária do documento;
- Decorado com o atributo [BsonRepresentation(BsonType.ObjectId)] para permitir a passagem do parâmetro como string de tipo em vez de uma estrutura ObjectId. O Mongo lida com a conversão de string para ObjectId.

Ainda na pasta Models vamos criar a classe DatabaseSettings onde vamos definir as propriedades para armazenar a string de conexão com o MongoDB e o nome do banco de dados usado:

namespace AlunosApi.Models;

public class DatabaseSettings
{
    public string ConnectionString { get; set; } = null!;
    public string DatabaseName { get; set; } = null!;
}

A seguir defina no arquivo appsettings.json a string de conexão e o nome do banco :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "DatabaseSettings": {
    "ConnectionString": "mongodb://localhost:27017",
    "DatabaseName": "AlunosDB"

  }
}

A seguir vamos criar uma pasta Services no projeto e nesta pasta crie a classe AlunoService onde vamos definir as operações que iremos realizar para gerenciar as informações dos alunos no MongoDB:

using AlunosApi.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;

namespace AlunosApi.Services;

public class AlunoService
{
    private readonly IMongoCollection<Aluno> _AlunoCollection;

    public AlunoService(
        IOptions<DatabaseSettings> dabaseSettings)
    {
        var mongoClient = new MongoClient(dabaseSettings.Value.ConnectionString);
        var mongoDatabase = mongoClient.GetDatabase(dabaseSettings.Value.DatabaseName);
        _AlunoCollection = mongoDatabase.GetCollection<Aluno>("Aluno");
    }

    public async Task<List<Aluno>> GetAsync() =>
        await _AlunoCollection.Find(_ => true).ToListAsync();

    public async Task<Aluno?> GetAsync(string id) =>
        await _AlunoCollection.Find(x => x.Id == id).FirstOrDefaultAsync();

    public async Task CreateAsync(Aluno newAluno) =>
        await _AlunoCollection.InsertOneAsync(newAluno);

    public async Task UpdateAsync(string id, Aluno updatedAluno) =>
        await _AlunoCollection.ReplaceOneAsync(x => x.Id == id, updatedAluno);

    public async Task RemoveAsync(string id) => await
                   _AlunoCollection.DeleteOneAsync(x => x.Id == id);
}

No código acima usamos uma instância de IMongoCollection e definimos os métodos : GetAsync(), CreateAsync() , UpdateAsync() e DeleteAsync() para realizar as operações CRUD com o MongoDB.

Agora precisamos registrar os serviços no container DI e habilitar o CORS em nossa API. Faremos isso na classe Program:

using AlunosApi.Models;
using AlunosApi.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.Configure<DatabaseSettings>(builder.Configuration
                         .GetSection("DatabaseSettings"));


builder.Services.AddSingleton<AlunoService>();

var MyAllowedOrigins = "_myAllowedOrigins";
builder.Services.AddCors(options =>
{
    options.AddPolicy(MyAllowedOrigins,
           builder =>
           {
                builder.AllowAnyOrigin()
               .AllowAnyHeader()
               .AllowAnyMethod();
           });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();
app.UseCors(MyAllowedOrigins);

app.MapControllers();

app.Run();

Neste código registramos a injeção de dependência com as propriedades DatabaseSettings do arquivo appsettings.json. Além disso, a classe AlunoService é registrada com DI para dar suporte à injeção de construtor em classes consumidoras. O tempo de vida do serviço singleton é mais adequado porque AlunoService tem uma dependência direta do MongoClient.

Agora podemos criar o controlador AlunosController na pasta Controllers:

using AlunosApi.Models;
using AlunosApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace AlunosApi.Controllers;

[Route("api/[controller]")]
[ApiController]

public class AlunosController : ControllerBase
{
    private readonly AlunoService _alunoService;

    public AlunosController(AlunoService alunoService) =>
          _alunoService = alunoService;

    [HttpGet]
    public async Task<List<Aluno>> Get() => await _alunoService.GetAsync();

    [HttpGet("{id:length(24)}")]
    public async Task<ActionResult<Aluno>> Get(string id)
    {
        var Aluno = await _alunoService.GetAsync(id);

        if (Aluno is null)
        {
            return NotFound();
        }

        return Aluno;
    }

    [HttpPost]
    public async Task<IActionResult> Post(Aluno novoAluno)
    {
        await _alunoService.CreateAsync(novoAluno);

        return NoContent();
    }

    [HttpPut("{id:length(24)}")]
    public async Task<IActionResult> Update(string id, Aluno alunoAtualizado)
    {
        var Aluno = await _alunoService.GetAsync(id);

        if (Aluno is null)
        {
            return NotFound();
        }

        alunoAtualizado.Id = Aluno.Id;

        await _alunoService.UpdateAsync(id, alunoAtualizado);

        return NoContent();
    }

    [HttpDelete("{id:length(24)}")]
    public async Task<IActionResult> Delete(string id)
    {
        var Aluno = await _alunoService.GetAsync(id);

        if (Aluno is null)
        {
            return NotFound();
        }

        await _alunoService.RemoveAsync(id);

        return NoContent();
    }
}

No controlador usamos a classe AlunoService para implementar operações CRUD dentro do controlador da API

O controlador tem métodos de ação para suportar solicitações HTTP GET, POST, PUT e DELETE.

Executando o projeto neste momento iremos ver os endpoints exibidos na interface do Swagger:

Para incluir um novo aluno podemos usar o endpoint : POST /api/alunos e informar:

conforme mostra a figura abaixo:

Após incluir alguns alunos podemos consultar os dados usando o endpoint : GET /api/alunos

Podemos também usar o MongoDB Compass e acessar a os dados como mostrado abaixo:

Com isso temos uma Web API acessando um banco de dados MongoDB local mas podemos também usar o MongoDB em um container Docker e assim não teremos que instalar nada em nosso ambiente.

Na próxima parte do artigo iremos criar um contêiner Docker para o MongoDB e mostrar como acessar os dados no container.

Pegue o projeto aqui:  AlunosApi.zip  ...

'Sede pois, irmãos, pacientes até à vinda do Senhor. Eis que o lavrador espera o precioso fruto da terra, aguardando-o com paciência, até que receba a chuva temporã e serôdia.'
Tiago 5:7

Referências:


José Carlos Macoratti