Skip to main content

🚀Master User Authentication in .NET 8 Web API Email Confirmation, Password Reset, 2FA & Lockout with JWT & Identity🔐

🚀Master .NET 8 Web API with MongoDB in Docker!🛠️ Step-by-Step Tutorial for Scalable Solutions📈

🎉 Welcome back, Netcode-Hub community! 

We are diving into the exciting world of Docker and MongoDB! If you've been following our series, you know we've already covered how to run .NET Web API with SQLite, SQL Server, and PostgreSQL. Today, we're taking it a step further by showing you how to connect your .NET Web API to MongoDB, all within a Docker container! 🌐💻

Scenario

Imagine you’re working on a project that involves handling a large amount of unstructured data—like logs, real-time analytics, or IoT data. MongoDB, a NoSQL database, is perfect for this scenario due to its flexible schema design. By running your .NET Web API connected to MongoDB in a Docker container, you ensure a consistent environment across all stages of development, testing, and production. This setup allows you to quickly spin up instances, making your development workflow much more efficient and scalable.

Summary

In this tutorial, we'll walk you through:

  1. Setting Up MongoDB in Docker: We’ll start by pulling the official MongoDB image from Docker Hub and setting up a container.
  2. Configuring .NET Web API: Next, we'll modify our .NET Web API project to connect to the MongoDB instance.
  3. Running Everything Together: Finally, we'll use Docker Compose to orchestrate both the MongoDB and .NET Web API containers, ensuring seamless communication between them.
# Setup Connections 
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "mongodb://mongo:27017"
  },
  "MongoDB": {
    "DatabaseName": "MyMongoDatabase",
    "CollectionName": "MyMongoCollection"
  }
}

# Install the packages 
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="x.x.x" />
<PackageReference Include="MongoDB.Driver" Version="x.x.x" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="x.x.x" />

# Create Model
public class Product
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? Id { get; set; }
    [BsonElement("Name")]
    public string? Name { get; set; }
    [BsonElement("Description")]
    public string? Description { get; set; }
    [BsonElement("Quantity")]
    public int Quantity { get; set; }
}

# Create DB Context Class 
   public class ProductDbContext
 {
     private readonly IMongoDatabase _database;
     private readonly IConfiguration Configuration;
     public ProductDbContext(IConfiguration configuration)
     {
         Configuration = configuration;
         string connectionString = Configuration.GetConnectionString("DefaultConnection")!;
         string databaseName = Configuration.GetSection("MongoDB:DatabaseName").Value!;
         var client = new MongoClient(connectionString);
         _database = client.GetDatabase(databaseName);
     }
     public IMongoCollection<Product> Products =>
         _database.GetCollection<Product>(Configuration.GetSection("MongoDB:CollectionName").Value!);
 }

# Create Product Endpoint 
 public static class ProductEndpoints
 {
     public static void MapProductEndpoints(this IEndpointRouteBuilder routes)
     {
         var group = routes.MapGroup("/api/Product").WithTags(nameof(Product));
         group.MapGet("/", async (ProductDbContext db) =>
         {
             return await db.Products.FindAsync(_ => true).Result.ToListAsync();
         })
        .WithName("GetAllProducts")
        .WithOpenApi();

         group.MapGet("/{id}", async Task<Results<Ok<Product>, NotFound>> (string id, ProductDbContext db) =>
         {
             var filter = Builders<Product>.Filter.Eq(p => p.Id, id);
             var data = await db.Products.Find(filter).FirstOrDefaultAsync();
             return TypedResults.Ok(data);
         })
        .WithName("GetProductById")
        .WithOpenApi();

         group.MapPut("/{id}", async Task<Results<Ok, NotFound>> (string id, Product product, ProductDbContext db) =>
         {

             var affected = await db.Products.ReplaceOneAsync(m => m.Id == id, product);
             if (affected.MatchedCount > 0)
                 return TypedResults.Ok();
             else return TypedResults.NotFound();
         })
        .WithName("UpdateProduct")
        .WithOpenApi();

         group.MapPost("/", async (Product product, ProductDbContext db) =>
         {
             await db.Products.InsertOneAsync(product);
             return TypedResults.Created($"/api/Product/{product.Id}", product);
         })
        .WithName("CreateProduct")
        .WithOpenApi();

         group.MapDelete("/{id}", async Task<Results<Ok, NotFound>> (string id, ProductDbContext db) =>
         {
             var result = await db.Products.DeleteOneAsync(model => model.Id == id);
             if (result.DeletedCount > 0)
                 return TypedResults.Ok();
             else return TypedResults.NotFound();
         })
       .WithName("DeleteProduct")
       .WithOpenApi();
     }
 }

# Create Docker File
  # See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 80

# This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["DemoWebAPIWithMongoDbInDocker/DemoWebAPIWithMongoDbInDocker.csproj", "DemoWebAPIWithMongoDbInDocker/"]
RUN dotnet restore "./DemoWebAPIWithMongoDbInDocker/DemoWebAPIWithMongoDbInDocker.csproj"
COPY . .
WORKDIR "/src/DemoWebAPIWithMongoDbInDocker"
RUN dotnet build "./DemoWebAPIWithMongoDbInDocker.csproj" -c $BUILD_CONFIGURATION -o /app/build

# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./DemoWebAPIWithMongoDbInDocker.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "DemoWebAPIWithMongoDbInDocker.dll"]

# Create Docker-Compose File 
services:
  webapi:
    build: 
      context: .
      dockerfile: Dockerfile
    image: "myapi_mongo:latest"
    ports:
      - "5003:80"
    environment:
      - ASPNETCORE_URLS=http://+:80;
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__DefaultConnection=mongodb://mongo:27017
      - MongoDB__DatabaseName=MyMongoDatabase
      - MongoDB__CollectionName=MyMongoCollection
    depends_on:
      - mongo
    networks:
      - my_custom_network
  mongo:
    image: mongo:latest
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
    networks:
      - my_custom_network
networks:
  my_custom_network:
    external: false

volumes:
  mongo-data:

# Register Service And CORS
builder.Services.AddSingleton<ProductDbContext>();
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAllOrigins",
        builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        });
});
var app = builder.Build();

// Configure the HTTP request pipeline.

    app.UseSwagger();
    app.UseSwaggerUI();

app.UseCors("AllowAllOrigins");
//app.UseHttpsRedirection();

app.UseAuthorization();
app.MapControllers();
app.MapProductEndpoints();
app.Run();

Conclusion

Wow, we did it! 🚀 You've now mastered how to run your .NET Web API connected to MongoDB using Docker. This setup is incredibly powerful, providing you with a robust, scalable, and consistent environment that's perfect for handling large volumes of unstructured data.

In this tutorial, we've covered:

  1. Setting Up MongoDB in Docker: From pulling the image to running the container.
  2. Configuring .NET Web API: Connecting our API to the MongoDB instance.
  3. Orchestrating with Docker Compose: Ensuring seamless communication between services.

By implementing this, you’ve taken a significant step towards modernizing your development workflow. Whether you’re building real-time analytics applications, managing IoT data, or handling large logs, this Docker and MongoDB setup ensures that you’re ready to tackle any challenge with efficiency and scalability.

Comments

Popular Posts

Complete Employee Management System | .NET 8 Blazor Wasm & Web API - Perform CRUD, Print, PDF etc..

.NET 8 Clean Architecture with Blazor CRUD, JWT & Role Authorization using Identity & Refresh Token🔥

Employee Management System | .NET 8 Blazor Wasm- Profile & real-time data retrieval. Update 1