Skip to main content

๐Ÿš€Master User Authentication in .NET 8 Web API Email Confirmation, Password Reset, 2FA & Lockout with JWT & Identity๐Ÿ”

๐Ÿš€ Build & Run .NET Web API with PostgreSQL in Docker ๐Ÿ˜ – Ultimate Guide for Modern Development ๐ŸŒŸ


# Introduction

๐Ÿ‘‹ Hey, Netcode-Hub family! ๐Ÿš€ In our journey of mastering Web APIs, we've already explored connecting to SQLite and SQL Server databases within Docker. Today, we're diving into the world of PostgreSQL! ๐Ÿ˜✨


# Scenario

Imagine you're working on a project that requires a robust, scalable database solution. PostgreSQL is known for its advanced features, strong performance, and flexibility. Now, imagine taking that power and containerizing it with your .NET Web API in Docker. This setup not only simplifies deployment but also ensures consistency across different environments—perfect for development, testing, and production. Sounds amazing, right? I'll show you exactly how to build, configure, and run your Web API with PostgreSQL in Docker. Let's get started and take your skills to the next level! ๐ŸŽ‰


# Lets Start By Creating Connection String

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=sqlserver;Database=YoutubeProductDb;User Id=sa;Password=Netcode2024;TrustServerCertificate=true;"
  }
}


# Create Model

 public class Product
 {
     public int Id { get; set; }
     public string? Name { get; set; }
     public string? Description { get; set; }
     public int Qauntity { get; set; }
 }

 # Create DB Context

 public class ProductDbContext : DbContext
    {
        public ProductDbContext (DbContextOptions<ProductDbContext> options)
            : base(options)
        {
        }

        public DbSet<Product> Product { get; set; } = default!;
    }

# Create Product Endpoints

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.Product.ToListAsync();
        })
        .WithName("GetAllProducts")
        .WithOpenApi();

        group.MapGet("/{id}", async Task<Results<Ok<Product>, NotFound>> (int id, ProductDbContext db) =>
        {
            return await db.Product.AsNoTracking()
                .FirstOrDefaultAsync(model => model.Id == id)
                is Product model
                    ? TypedResults.Ok(model)
                    : TypedResults.NotFound();
        })
        .WithName("GetProductById")
        .WithOpenApi();

        group.MapPut("/{id}", async Task<Results<Ok, NotFound>> (int id, Product product, ProductDbContext db) =>
        {
            var affected = await db.Product
                .Where(model => model.Id == id)
                .ExecuteUpdateAsync(setters => setters
                    .SetProperty(m => m.Id, product.Id)
                    .SetProperty(m => m.Name, product.Name)
                    .SetProperty(m => m.Description, product.Description)
                    .SetProperty(m => m.Qauntity, product.Qauntity)
                    );
            return affected == 1 ? TypedResults.Ok() : TypedResults.NotFound();
        })
        .WithName("UpdateProduct")
        .WithOpenApi();

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

        group.MapDelete("/{id}", async Task<Results<Ok, NotFound>> (int id, ProductDbContext db) =>
        {
            var affected = await db.Product
                .Where(model => model.Id == id)
                .ExecuteDeleteAsync();
            return affected == 1 ? TypedResults.Ok() : 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 ["DemoWebAPIWithPostgreSqlInDocker/DemoWebAPIWithPostgreSqlInDocker.csproj", "DemoWebAPIWithPostgreSqlInDocker/"]
RUN dotnet restore "./DemoWebAPIWithPostgreSqlInDocker/DemoWebAPIWithPostgreSqlInDocker.csproj"
COPY . .
WORKDIR "/src/DemoWebAPIWithPostgreSqlInDocker"
RUN dotnet build "./DemoWebAPIWithPostgreSqlInDocker.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 "./DemoWebAPIWithPostgreSqlInDocker.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", "DemoWebAPIWithPostgreSqlInDocker.dll"]

# Create docker-Compose  File

services:
    webapi:
      build:  
         context: .
         dockerfile: Dockerfile
      image: webapi_posgresql_v1
      ports:
         - "5003:80"
      environment:
         - ASPNETCORE_URLS=http://+:80
         - ASPNETCORE_ENVIRONMENT=Development
         - ConnectionsStrings__DefaultConnection=Host=postgreserver;username=postgres;password=NetcodeHub2024;database=MyDb; TrustServerCertificate=true;
      depends_on:
          - postgreserver

    postgreserver:
      image: postgres:latest
      environment:
        POSTGRES_DB: MyDb
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: NetcodeHub2024
      ports:
        - "5432:5432"
      volumes:
          - pgdata:/var/lib/postgresql/data
  networks:
    default:
      name: my_custom_network 
  
  volumes:
    pgdata:

# Create Migration Service

   public class MigrationService
 {
     public static void InitializeMigration(IApplicationBuilder app)

     {
         using var serviceScope = app.ApplicationServices.CreateScope();
         serviceScope.ServiceProvider.GetService<ProductDbContext>()!.Database.Migrate();
     }
 }


  # Register Database, Migration Service, CORS and Endpoint

builder.Services.AddDbContext<ProductDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAllOrigins", builder =>
    {
        builder.AllowAnyOrigin()
        .AllowAnyHeader()
        .AllowAnyMethod();
    });
});
var app = builder.Build();
MigrationService.InitializeMigration(app);

// Configure the HTTP request pipeline.
    app.UseSwagger();
    app.UseSwaggerUI();
//app.UseHttpsRedirection();
app.UseCors("AllowAllOrigins");
app.MapProductEndpoints();
   app.Run();

    

# Run This Command In Console 


    docker-compose up --build

# Conclusion

And that’s it, folks! in this tutorial, we have created fully functional .NET Web API connected to SQL Server, all running smoothly in Docker containers. This setup not only enhances your development workflow but also prepares your application for scalable, production-ready deployments. ๐ŸŒŸ














# Here's a follow-up section to encourage engagement and support for Netcode-Hub:

๐ŸŒŸ Get in touch with Netcode-Hub! ๐Ÿ“ซ

1. GitHub: [Explore Repositories] ๐ŸŒ

2. Twitter: [Stay Updated] ๐Ÿฆ

3. Facebook: [Connect Here]๐Ÿ“˜

4. LinkedIn: [Professional Network]๐Ÿ”—

5. Email: [business.netcodehub@gmail.com] ๐Ÿ“ง

# ☕️ If you've found value in Netcode-Hub's work, consider supporting the channel with a coffee!

1. Buy Me a Coffee: [Support Netcode-Hub] ☕️

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