From 233da7e7ea2211da406401d9ff3c174009084183 Mon Sep 17 00:00:00 2001 From: Ariel Roffman Date: Wed, 13 May 2026 19:12:36 -0400 Subject: [PATCH] initial commit --- .dockerignore | 6 +++ .gitignore | 12 +++++ Controllers/TodoItemsController.cs | 74 ++++++++++++++++++++++++++++++ Data/AppDbContext.cs | 14 ++++++ Dockerfile | 15 ++++++ Models/TodoItem.cs | 15 ++++++ Program.cs | 29 ++++++++++++ Properties/launchSettings.json | 31 +++++++++++++ README.md | 34 +++++++++++++- appsettings.Development.json | 8 ++++ appsettings.json | 12 +++++ demo001.csproj | 19 ++++++++ demo001.http | 6 +++ demo001.sln | 24 ++++++++++ docker-compose.yml | 27 +++++++++++ remotebuild.txt | 48 +++++++++++++++++++ 16 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Controllers/TodoItemsController.cs create mode 100644 Data/AppDbContext.cs create mode 100644 Dockerfile create mode 100644 Models/TodoItem.cs create mode 100644 Program.cs create mode 100644 Properties/launchSettings.json create mode 100644 appsettings.Development.json create mode 100644 appsettings.json create mode 100644 demo001.csproj create mode 100644 demo001.http create mode 100644 demo001.sln create mode 100644 docker-compose.yml create mode 100644 remotebuild.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1a43a70 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +bin/ +obj/ +**/*.user +**/*.suo +**/*.vs +**/.git diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4228ac7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +bin/ +obj/ +.vs/ +*.user +*.suo +*.cache +*.db +*.bak +.DS_Store +.nuget/ +.env +docker-compose.override.yml diff --git a/Controllers/TodoItemsController.cs b/Controllers/TodoItemsController.cs new file mode 100644 index 0000000..3b9e479 --- /dev/null +++ b/Controllers/TodoItemsController.cs @@ -0,0 +1,74 @@ +using Demo001.Data; +using Demo001.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Demo001.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class TodoItemsController : ControllerBase +{ + private readonly AppDbContext _context; + + public TodoItemsController(AppDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> GetTodoItems() + { + return await _context.TodoItems.ToListAsync(); + } + + [HttpGet("{id}")] + public async Task> GetTodoItem(int id) + { + var item = await _context.TodoItems.FindAsync(id); + return item is null ? NotFound() : item; + } + + [HttpPost] + public async Task> CreateTodoItem(TodoItem item) + { + _context.TodoItems.Add(item); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item); + } + + [HttpPut("{id}")] + public async Task UpdateTodoItem(int id, TodoItem item) + { + if (id != item.Id) + { + return BadRequest(); + } + + if (!await _context.TodoItems.AnyAsync(x => x.Id == id)) + { + return NotFound(); + } + + _context.Entry(item).State = EntityState.Modified; + await _context.SaveChangesAsync(); + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteTodoItem(int id) + { + var item = await _context.TodoItems.FindAsync(id); + if (item is null) + { + return NotFound(); + } + + _context.TodoItems.Remove(item); + await _context.SaveChangesAsync(); + + return NoContent(); + } +} diff --git a/Data/AppDbContext.cs b/Data/AppDbContext.cs new file mode 100644 index 0000000..1f4eabd --- /dev/null +++ b/Data/AppDbContext.cs @@ -0,0 +1,14 @@ +using Demo001.Models; +using Microsoft.EntityFrameworkCore; + +namespace Demo001.Data; + +public class AppDbContext : DbContext +{ + public AppDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet TodoItems => Set(); +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9cf7cbc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build +WORKDIR /src +COPY *.csproj ./ +RUN dotnet restore +COPY . . +RUN dotnet publish -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=build /app/publish . +ENTRYPOINT ["dotnet", "demo001.dll"] diff --git a/Models/TodoItem.cs b/Models/TodoItem.cs new file mode 100644 index 0000000..4738c0d --- /dev/null +++ b/Models/TodoItem.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace Demo001.Models; + +public class TodoItem +{ + public int Id { get; set; } + + [Required] + public string Title { get; set; } = string.Empty; + + public string? Description { get; set; } + + public bool IsComplete { get; set; } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..2e4d367 --- /dev/null +++ b/Program.cs @@ -0,0 +1,29 @@ +using Demo001.Data; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); + +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") + ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); + +builder.Services.AddDbContext(options => + options.UseNpgsql(connectionString)); + +builder.Services.AddControllers(); +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseHttpsRedirection(); +app.MapControllers(); + +using (var scope = app.Services.CreateScope()) +{ + var db = scope.ServiceProvider.GetRequiredService(); + db.Database.Migrate(); +} + +app.Run(); diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..31414c8 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:44304", + "sslPort": 0 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5136", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/README.md b/README.md index 67d1cdc..65e3280 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# This is a demo -Thanks for reading. Bye! \ No newline at end of file +# demo001 + +A simple ASP.NET Core Web API CRUD app using PostgreSQL. + +## Local development + +Requirements: +- .NET SDK +- Docker + +### Run with docker-compose + +```powershell +cd .\demo001 +docker-compose up --build +``` + +The API will be available at `http://localhost:5000`. + +### API endpoints + +- `GET /api/TodoItems` +- `GET /api/TodoItems/{id}` +- `POST /api/TodoItems` +- `PUT /api/TodoItems/{id}` +- `DELETE /api/TodoItems/{id}` + +### Notes + +- `Dockerfile` is ready for container builds. +- `docker-compose.yml` starts PostgreSQL and the API locally. +- Later you can reuse the Docker image for Kubernetes deployment. diff --git a/appsettings.Development.json b/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..c221823 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,12 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Host=localhost;Port=5432;Database=demo;Username=demo;Password=demo" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/demo001.csproj b/demo001.csproj new file mode 100644 index 0000000..15d6626 --- /dev/null +++ b/demo001.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + enable + enable + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + diff --git a/demo001.http b/demo001.http new file mode 100644 index 0000000..67f7889 --- /dev/null +++ b/demo001.http @@ -0,0 +1,6 @@ +@demo001_HostAddress = http://localhost:5136 + +GET {{demo001_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/demo001.sln b/demo001.sln new file mode 100644 index 0000000..6a758ec --- /dev/null +++ b/demo001.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo001", "demo001.csproj", "{5419A3DA-A418-8B47-148E-7AF11DAED4B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5419A3DA-A418-8B47-148E-7AF11DAED4B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5419A3DA-A418-8B47-148E-7AF11DAED4B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5419A3DA-A418-8B47-148E-7AF11DAED4B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5419A3DA-A418-8B47-148E-7AF11DAED4B1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CD15261C-C190-42D8-B39F-C698F93D1AB4} + EndGlobalSection +EndGlobal diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a067f0a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.9' + +services: + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: demo + POSTGRES_PASSWORD: demo + POSTGRES_DB: demo + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + + api: + build: + context: . + dockerfile: Dockerfile + environment: + ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Database=demo;Username=demo;Password=demo" + ports: + - "5000:80" + depends_on: + - db + +volumes: + pgdata: diff --git a/remotebuild.txt b/remotebuild.txt new file mode 100644 index 0000000..546ec67 --- /dev/null +++ b/remotebuild.txt @@ -0,0 +1,48 @@ +Use VS Code Remote SSH to build on the Linux server +1. Install the Remote SSH extension +Install Remote - SSH from the VS Code Extensions view. +2. Add your SSH host +Open Command Palette: Ctrl+Shift+P +Run Remote-SSH: Add New SSH Host... +Enter something like: +ssh root@your.remote.server +Choose the SSH config file to save it. +3. Connect to the remote host +Open Command Palette: Ctrl+Shift+P +Run Remote-SSH: Connect to Host... +Select root@your.remote.server +VS Code will open a new window connected to the remote machine. +4. Open your project folder on the remote server +In the remote VS Code window, use File > Open Folder... +Open the project directory on the Linux server +If your project is only local, copy it to the remote host first, or clone it there from git. +5. Build and run remotely +Open a terminal in VS Code (`Ctrl+``) +This terminal runs on the remote Linux machine +Run: +dotnet restore +dotnet build +dotnet run +6. If you want Docker/Compose on the remote +Since you have root access on the server, you can install Docker there and use it remotely: + +Install Docker on remote Linux +Install Docker Compose plugin if needed +Run: +docker compose up --build +7. Optional: Use remote ports +If your API listens on 5000, you can forward that port from remote to local using VS Code Remote Explorer or the prompt when the app starts. +Why this works +VS Code Remote SSH lets you edit locally while using the remote machine for: +building +restoring packages +running the app +optionally building Docker images +Quick summary +Install Remote - SSH +Add root@your.server +Connect & open remote folder +Build in remote terminal +If you want, I can also give you the exact ~/.ssh/config entry and the commands to install Docker on the remote Linux server. + +Raptor mini (Preview) • 1x \ No newline at end of file