From 4eef6ec88c5c257abdb2625dc1bdf437062899fe Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Mon, 11 Apr 2022 16:33:57 -0300 Subject: [PATCH] create aspnet api with postgresql This version added a compose application using: * ASP.Net API Core * EntityFramework Core * Postgresql Signed-off-by: Eduardo Silva --- README.md | 2 + aspnet-api-postgresql/.gitignore | 285 ++++++++++++++++++ aspnet-api-postgresql/README.md | 62 ++++ aspnet-api-postgresql/api/.dockerignore | 284 +++++++++++++++++ .../api/Controllers/HealthCheckController.cs | 36 +++ .../Infrastructure/ApplicationDbContext.cs | 11 + ...0220411183355_InititalCreation.Designer.cs | 28 ++ .../20220411183355_InititalCreation.cs | 19 ++ .../ApplicationDbContextModelSnapshot.cs | 26 ++ aspnet-api-postgresql/api/Program.cs | 49 +++ .../api/Properties/launchSettings.json | 31 ++ .../api/appsettings.Development.json | 8 + aspnet-api-postgresql/api/appsettings.json | 12 + .../api/aspnet-api-postgresql.csproj | 26 ++ .../aspnet-api-postgresql.sln | 22 ++ aspnet-api-postgresql/docker-compose.yml | 28 ++ aspnet-api-postgresql/output.png | Bin 0 -> 44511 bytes 17 files changed, 929 insertions(+) create mode 100644 aspnet-api-postgresql/.gitignore create mode 100644 aspnet-api-postgresql/README.md create mode 100644 aspnet-api-postgresql/api/.dockerignore create mode 100644 aspnet-api-postgresql/api/Controllers/HealthCheckController.cs create mode 100644 aspnet-api-postgresql/api/Infrastructure/ApplicationDbContext.cs create mode 100644 aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.Designer.cs create mode 100644 aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.cs create mode 100644 aspnet-api-postgresql/api/Infrastructure/Database/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 aspnet-api-postgresql/api/Program.cs create mode 100644 aspnet-api-postgresql/api/Properties/launchSettings.json create mode 100644 aspnet-api-postgresql/api/appsettings.Development.json create mode 100644 aspnet-api-postgresql/api/appsettings.json create mode 100644 aspnet-api-postgresql/api/aspnet-api-postgresql.csproj create mode 100644 aspnet-api-postgresql/aspnet-api-postgresql.sln create mode 100644 aspnet-api-postgresql/docker-compose.yml create mode 100644 aspnet-api-postgresql/output.png diff --git a/README.md b/README.md index 4627833..b81b98c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ These samples provide a starting point for how to integrate different services u ## Samples of Docker Compose applications with multiple integrated services - [`ASP.NET / MS-SQL`](https://github.com/docker/awesome-compose/tree/master/aspnet-mssql) - Sample ASP.NET core application with MS SQL server database. +- [`ASP.NET / Postgresql`](https://github.com/docker/awesome-compose/tree/master/aspnet-api-postgresql) - Sample ASP.NET core application +with Postgresql server database. - [`Elasticsearch / Logstash / Kibana`](https://github.com/docker/awesome-compose/tree/master/elasticsearch-logstash-kibana) - Sample Elasticsearch, Logstash, and Kibana stack. - [`Go / NGINX / MySQL`](https://github.com/docker/awesome-compose/tree/master/nginx-golang-mysql) - Sample Go application with an Nginx proxy and a MySQL database. diff --git a/aspnet-api-postgresql/.gitignore b/aspnet-api-postgresql/.gitignore new file mode 100644 index 0000000..1f3754d --- /dev/null +++ b/aspnet-api-postgresql/.gitignore @@ -0,0 +1,285 @@ + +# Created by https://www.gitignore.io/api/csharp + +### Csharp ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ +Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ +tools/Cake.CoreCLR +.vscode +tools +.dotnet + +# .env file contains default environment variables for docker +.env + +.DS_Store \ No newline at end of file diff --git a/aspnet-api-postgresql/README.md b/aspnet-api-postgresql/README.md new file mode 100644 index 0000000..ddb8685 --- /dev/null +++ b/aspnet-api-postgresql/README.md @@ -0,0 +1,62 @@ +## Compose sample application: ASP.Net API with Postgresql database + +Project Structure +``` +. +├── api +│ ├── appsettings.json +│ ├── ... +└── docker-compose.yaml +``` +[_docker-compose.yaml](docker-compose.yml) + +``` +services: + api: + image: mcr.microsoft.com/dotnet/sdk + container_name: "api" + ports: + - 5000:5000 + ... + db: + image: postgres:10.5 + restart: always + ... +``` + +The compose file defines an application with two services `api` and `db`. The api service is configured without a Dockerfile and to run using your local volume in `watch` mode. + +## Deploy with docker-compose + +``` +$ docker-compose up -d +Pulling db (postgres:10.5)... +10.5: Pulling from library/postgres +... +Status: Downloaded newer image for postgres:10.5 +Pulling api (mcr.microsoft.com/dotnet/sdk:)... +latest: Pulling from dotnet/sdk +... +Status: Downloaded newer image for mcr.microsoft.com/dotnet/sdk:latest +Creating aspnet-api-postgresql_db_1 ... done +Creating api ... done +``` + +## Expected result + +``` +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +48c8a8911cfb mcr.microsoft.com/dotnet/sdk "dotnet watch run --…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp api +84082957734e postgres:10.5 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp aspnet-api-postgresql_db_1 +``` + +After the application starts, navigate to http://localhost:5000/swagger/index.html in your web browser. + +![page](output.png) + +Stop and remove the containers + +``` +$ docker-compose down +``` \ No newline at end of file diff --git a/aspnet-api-postgresql/api/.dockerignore b/aspnet-api-postgresql/api/.dockerignore new file mode 100644 index 0000000..084da0b --- /dev/null +++ b/aspnet-api-postgresql/api/.dockerignore @@ -0,0 +1,284 @@ +# Created by https://www.gitignore.io/api/csharp + +### Csharp ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ +Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/ +tools/Cake.CoreCLR +.vscode +tools +.dotnet +Dockerfile + +# .env file contains default environment variables for docker +.env +.git/ \ No newline at end of file diff --git a/aspnet-api-postgresql/api/Controllers/HealthCheckController.cs b/aspnet-api-postgresql/api/Controllers/HealthCheckController.cs new file mode 100644 index 0000000..8eefc8a --- /dev/null +++ b/aspnet-api-postgresql/api/Controllers/HealthCheckController.cs @@ -0,0 +1,36 @@ +using aspnet_api_postgresql.Infrastructure.Database; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace aspnet_api_postgresql.Controllers; + +[ApiController] +[Route("[controller]")] +public class HealthCheckController : ControllerBase +{ + private readonly ILogger _logger; + private readonly ApplicationDbContext _dbContext; + + public HealthCheckController(ApplicationDbContext dbContext, ILogger logger) + { + _logger = logger; + _dbContext = dbContext; + } + + [HttpGet] + public string Ping() + { + try + { + _dbContext.Database.OpenConnection(); + _dbContext.Database.ExecuteSqlRaw("SELECT 1"); + _dbContext.Database.CloseConnection(); + return "OK"; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error connecting to database"); + return "Error connecting to database"; + } + } +} diff --git a/aspnet-api-postgresql/api/Infrastructure/ApplicationDbContext.cs b/aspnet-api-postgresql/api/Infrastructure/ApplicationDbContext.cs new file mode 100644 index 0000000..2a8e9f5 --- /dev/null +++ b/aspnet-api-postgresql/api/Infrastructure/ApplicationDbContext.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; + +namespace aspnet_api_postgresql.Infrastructure.Database; +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + +} \ No newline at end of file diff --git a/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.Designer.cs b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.Designer.cs new file mode 100644 index 0000000..04a53b6 --- /dev/null +++ b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.Designer.cs @@ -0,0 +1,28 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using aspnet_api_postgresql.Infrastructure.Database; + +#nullable disable + +namespace aspnet_api_postgresql.Infrastructure.Database.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20220411183355_InititalCreation")] + partial class InititalCreation + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.cs b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.cs new file mode 100644 index 0000000..c265d42 --- /dev/null +++ b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/20220411183355_InititalCreation.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace aspnet_api_postgresql.Infrastructure.Database.Migrations +{ + public partial class InititalCreation : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/ApplicationDbContextModelSnapshot.cs b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..249398a --- /dev/null +++ b/aspnet-api-postgresql/api/Infrastructure/Database/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,26 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using aspnet_api_postgresql.Infrastructure.Database; + +#nullable disable + +namespace aspnet_api_postgresql.Infrastructure.Database.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-api-postgresql/api/Program.cs b/aspnet-api-postgresql/api/Program.cs new file mode 100644 index 0000000..f12a5a8 --- /dev/null +++ b/aspnet-api-postgresql/api/Program.cs @@ -0,0 +1,49 @@ +using System.Reflection; +using aspnet_api_postgresql.Infrastructure.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddDbContext(options => + options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")) + .UseSnakeCaseNamingConvention()); + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(_ => +{ + _.SwaggerDoc("v1", new OpenApiInfo + { + Version = "v1", + Title = "ASP.NET Core Web API", + }); + + var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + _.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); + +}); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + using (var scope = app.Services.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + db.Database.Migrate(); + } + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/aspnet-api-postgresql/api/Properties/launchSettings.json b/aspnet-api-postgresql/api/Properties/launchSettings.json new file mode 100644 index 0000000..b69d0c9 --- /dev/null +++ b/aspnet-api-postgresql/api/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:47446", + "sslPort": 44370 + } + }, + "profiles": { + "aspnet_api_postgresql": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7234;http://localhost:5260", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/aspnet-api-postgresql/api/appsettings.Development.json b/aspnet-api-postgresql/api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/aspnet-api-postgresql/api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnet-api-postgresql/api/appsettings.json b/aspnet-api-postgresql/api/appsettings.json new file mode 100644 index 0000000..2aa172f --- /dev/null +++ b/aspnet-api-postgresql/api/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultConnection": "Host=db;Username=postgres;Password=postgres;Database=aspnetapipostgresqldb" + } +} \ No newline at end of file diff --git a/aspnet-api-postgresql/api/aspnet-api-postgresql.csproj b/aspnet-api-postgresql/api/aspnet-api-postgresql.csproj new file mode 100644 index 0000000..9511ce4 --- /dev/null +++ b/aspnet-api-postgresql/api/aspnet-api-postgresql.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + enable + enable + aspnet_api_postgresql + + + true + $(NoWarn);1591 + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/aspnet-api-postgresql/aspnet-api-postgresql.sln b/aspnet-api-postgresql/aspnet-api-postgresql.sln new file mode 100644 index 0000000..34b5309 --- /dev/null +++ b/aspnet-api-postgresql/aspnet-api-postgresql.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30114.105 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aspnet-api-postgresql", "api\aspnet-api-postgresql.csproj", "{8260F100-34F4-4DC3-B6A5-FCF28A4DBEC4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8260F100-34F4-4DC3-B6A5-FCF28A4DBEC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8260F100-34F4-4DC3-B6A5-FCF28A4DBEC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8260F100-34F4-4DC3-B6A5-FCF28A4DBEC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8260F100-34F4-4DC3-B6A5-FCF28A4DBEC4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/aspnet-api-postgresql/docker-compose.yml b/aspnet-api-postgresql/docker-compose.yml new file mode 100644 index 0000000..38e60eb --- /dev/null +++ b/aspnet-api-postgresql/docker-compose.yml @@ -0,0 +1,28 @@ +version: '3.7' +services: + api: + image: mcr.microsoft.com/dotnet/sdk + container_name: "api" + ports: + - 5000:5000 + working_dir: /api + volumes: + - ./api:/api + command: ["dotnet", "watch", "run", "--urls=http://0.0.0.0:5000/"] + depends_on: + - "db" + db: + image: postgres:10.5 + restart: always + environment: + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "postgres" + POSTGRES_DB: "aspnetapipostgresqldb" + logging: + options: + max-size: 10m + max-file: "3" + ports: + - '5432:5432' + volumes: + - ./postgres-data:/var/lib/postgresql/data \ No newline at end of file diff --git a/aspnet-api-postgresql/output.png b/aspnet-api-postgresql/output.png new file mode 100644 index 0000000000000000000000000000000000000000..1f660dca93f0c7af963ad7606eeae07f84d8b09a GIT binary patch literal 44511 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