Compare commits
46 Commits
test
...
connection
| Author | SHA1 | Date | |
|---|---|---|---|
| aaea2c30a5 | |||
| 3ed9a15d09 | |||
| 5ef25d601f | |||
| 810f23f814 | |||
| 8d8a7a4c77 | |||
| b26c553d12 | |||
| 0ab8d7f7d1 | |||
| 998a4d5ab9 | |||
| b638c48104 | |||
| ada6967234 | |||
| 286a9eff72 | |||
| ebf8237be6 | |||
| 6c34f3e380 | |||
| fb578026eb | |||
| 57391d3e51 | |||
| 277d6b99fd | |||
| bbfac5eb07 | |||
| 4663e10f96 | |||
| b393abe948 | |||
| 3e4372c1b7 | |||
| 6b53139fd4 | |||
| e941649d75 | |||
| 3808adb6db | |||
| 8ee14255ce | |||
| 7c324e9647 | |||
| 5d4e351982 | |||
| 1739961bc2 | |||
| 567e5abf07 | |||
| c27971609a | |||
| 41251bb110 | |||
| f53e289f51 | |||
| 23ca30f084 | |||
| a1a1a667b3 | |||
| 12d56ebcc1 | |||
| 54be2c8732 | |||
| af470ea869 | |||
| 1446803fb8 | |||
| 0929ca2d94 | |||
| 39b7f4f3b3 | |||
| 79b66cb8b4 | |||
| 708966fcf8 | |||
| d3ba42e57a | |||
| 716d75a072 | |||
| 61f0dab8df | |||
| e78e5b205f | |||
| ddb5223572 |
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -37,12 +37,21 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
New-Item -Path .\.sonar\scanner -ItemType Directory
|
New-Item -Path .\.sonar\scanner -ItemType Directory
|
||||||
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
|
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
|
||||||
|
|
||||||
|
- name: Install dotnet-coverage tool
|
||||||
|
run: dotnet tool install --global dotnet-coverage
|
||||||
- name: Build and analyze
|
- name: Build and analyze
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
SQLSERVER_DB_SERVER: ${{ secrets.SQLSERVER_DB_SERVER }}
|
||||||
|
MONGO_DB_SERVER: ${{ secrets.MONGO_DB_SERVER }}
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
.\.sonar\scanner\dotnet-sonarscanner begin /k:"csimonapastore_BasicDotnetTemplate" /o:"csimonapastore-github" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
|
.\.sonar\scanner\dotnet-sonarscanner begin /k:"csimonapastore_BasicDotnetTemplate" /o:"csimonapastore-github" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.exclusions="**/Migrations/**.cs, **/Models/Database/**.cs, **/Core/Database/**.cs"
|
||||||
dotnet build
|
dotnet restore
|
||||||
|
dotnet build --no-incremental
|
||||||
|
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
|
||||||
|
dotnet test ./MainProject.Tests/MainProject.Tests.csproj --collect "Code Coverage" --results-directory "./TestResults"
|
||||||
|
Get-Content -Path "coverage.xml"
|
||||||
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
|
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
**/obj
|
**/obj
|
||||||
**/bin
|
**/bin
|
||||||
appsettings.*.json
|
**/appsettings.*.json
|
||||||
|
**/coverage*.xml
|
||||||
|
.fake
|
||||||
27
.vscode/launch.json
vendored
27
.vscode/launch.json
vendored
@@ -2,18 +2,13 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
"name": ".NET Rest Api - Watch",
|
||||||
// Use hover for the description of the existing attributes
|
|
||||||
// For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
|
|
||||||
"name": ".NET Core Launch (console)",
|
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
"program": "${workspaceFolder}/MainProject/bin/Debug/net8.0/MainProject.dll",
|
||||||
"program": "${workspaceFolder}/bin/Debug/net8.0/BasicDotnetTemplate.dll",
|
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
|
||||||
"console": "internalConsole",
|
"console": "internalConsole",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"env": {
|
"env": {
|
||||||
@@ -22,17 +17,31 @@
|
|||||||
"ASPNETCORE_DETAILEDERRORS": "1",
|
"ASPNETCORE_DETAILEDERRORS": "1",
|
||||||
"ASPNETCORE_SHUTDOWNTIMEOUTSECONDS": "3"
|
"ASPNETCORE_SHUTDOWNTIMEOUTSECONDS": "3"
|
||||||
},
|
},
|
||||||
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
|
||||||
"serverReadyAction": {
|
"serverReadyAction": {
|
||||||
"action": "openExternally",
|
"action": "openExternally",
|
||||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
|
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
|
||||||
"uriFormat": "%s/swagger"
|
"uriFormat": "%s/swagger"
|
||||||
},
|
},
|
||||||
|
"postDebugTask": "watch"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": ".NET Core Attach",
|
"name": ".NET Core Attach",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "attach"
|
"request": "attach"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"tasks": {
|
||||||
|
"label": "watch",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"watch",
|
||||||
|
"run"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
6
.vscode/tasks.json
vendored
6
.vscode/tasks.json
vendored
@@ -7,7 +7,7 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/BasicDotnetTemplate.csproj",
|
"${workspaceFolder}/BasicDotnetTemplate.sln",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
],
|
],
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"publish",
|
"publish",
|
||||||
"${workspaceFolder}/BasicDotnetTemplate.csproj",
|
"${workspaceFolder}/BasicDotnetTemplate.sln",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
],
|
],
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"watch",
|
"watch",
|
||||||
"run",
|
"run",
|
||||||
"--project",
|
"--project",
|
||||||
"${workspaceFolder}/BasicDotnetTemplate.csproj"
|
"${workspaceFolder}/BasicDotnetTemplate.sln"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
|
||||||
<PackageReference Include="NLog" Version="5.2.8" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
28
BasicDotnetTemplate.sln
Normal file
28
BasicDotnetTemplate.sln
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.0.31903.59
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MainProject", "MainProject\MainProject.csproj", "{5BC4F94C-35BC-4436-A107-9D85E53A9E84}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MainProject.Tests", "MainProject.Tests\MainProject.Tests.csproj", "{A672CB00-DC99-4847-A384-B857C5E69301}"
|
||||||
|
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
|
||||||
|
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A672CB00-DC99-4847-A384-B857C5E69301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A672CB00-DC99-4847-A384-B857C5E69301}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A672CB00-DC99-4847-A384-B857C5E69301}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A672CB00-DC99-4847-A384-B857C5E69301}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
45
MainProject.Tests/Controllers/RootController_Tests.cs
Normal file
45
MainProject.Tests/Controllers/RootController_Tests.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Controllers;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class RootController_Test
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void GetRoot_Valid()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RootController rootController = new RootController();
|
||||||
|
var result = rootController.GetRoot();
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
var data = (OkResult)result;
|
||||||
|
Assert.IsTrue(data.StatusCode == 200);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail($"Data is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
MainProject.Tests/Controllers/VersionController_Tests.cs
Normal file
104
MainProject.Tests/Controllers/VersionController_Tests.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Controllers;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class BaseController_Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void BaseController_NullConfiguration()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
||||||
|
var exception = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = new VersionController(null);
|
||||||
|
exception = false;
|
||||||
|
Assert.Fail($"This test should not pass as configuration is null");
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Assert.IsTrue(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void VersionController_GetVersion_Valid()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IConfiguration configuration = TestUtils.CreateConfiguration();
|
||||||
|
VersionController versionController = new VersionController(configuration);
|
||||||
|
var result = versionController.GetVersion();
|
||||||
|
var objectResult = ((ObjectResult)result).Value;
|
||||||
|
if (objectResult != null)
|
||||||
|
{
|
||||||
|
var data = (BaseResponse)objectResult;
|
||||||
|
if (data.Data != null)
|
||||||
|
{
|
||||||
|
AppSettings appSettings = new AppSettings();
|
||||||
|
configuration.GetSection("AppSettings").Bind(appSettings);
|
||||||
|
string version = data.Data != null ? (string)data.Data : "";
|
||||||
|
Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && (version == appSettings.Settings?.Version));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail($"Unable to convert response value to BaseResponse because Data is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail($"Data is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void VersionController_GetVersion_NoVersion()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
|
||||||
|
var configuration = TestUtils.CreateEmptyConfiguration(System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "emptyAppsettings.json");
|
||||||
|
VersionController versionController = new VersionController(configuration);
|
||||||
|
var result = versionController.GetVersion();
|
||||||
|
var objectResult = ((ObjectResult)result).Value;
|
||||||
|
if (objectResult != null)
|
||||||
|
{
|
||||||
|
var data = (BaseResponse)objectResult;
|
||||||
|
Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && String.IsNullOrEmpty(data.Data));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail($"Response value is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
MainProject.Tests/JsonData/appsettings.json
Normal file
27
MainProject.Tests/JsonData/appsettings.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"AppSettings" :
|
||||||
|
{
|
||||||
|
"Settings": {
|
||||||
|
"Name": "MainProject",
|
||||||
|
"Version": "v1.0",
|
||||||
|
"Description": "This template contains basic configuration for a .Net 8 backend"
|
||||||
|
},
|
||||||
|
"DatabaseSettings": {
|
||||||
|
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
|
||||||
|
"MongoDbConnectionString": "MONGO_DB_SERVER",
|
||||||
|
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
|
||||||
|
},
|
||||||
|
"OpenApiSettings": {
|
||||||
|
"TermsOfServiceUrl": "",
|
||||||
|
"OpenApiContact": {
|
||||||
|
"Name": "",
|
||||||
|
"Url": ""
|
||||||
|
},
|
||||||
|
"OpenApiLicense": {
|
||||||
|
"Name": "MIT License",
|
||||||
|
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
27
MainProject.Tests/JsonData/completeAppSettings.json
Normal file
27
MainProject.Tests/JsonData/completeAppSettings.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"AppSettings" :
|
||||||
|
{
|
||||||
|
"Settings": {
|
||||||
|
"Name": "MainProject",
|
||||||
|
"Version": "v1.0",
|
||||||
|
"Description": "This template contains basic configuration for a .Net 8 backend"
|
||||||
|
},
|
||||||
|
"DatabaseSettings": {
|
||||||
|
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
|
||||||
|
"MongoDbConnectionString": "MONGO_DB_SERVER",
|
||||||
|
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
|
||||||
|
},
|
||||||
|
"OpenApiSettings": {
|
||||||
|
"TermsOfServiceUrl": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md",
|
||||||
|
"OpenApiContact": {
|
||||||
|
"Name": "README",
|
||||||
|
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/README.md"
|
||||||
|
},
|
||||||
|
"OpenApiLicense": {
|
||||||
|
"Name": "MIT License",
|
||||||
|
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
MainProject.Tests/JsonData/emptyAppsettings.json
Normal file
7
MainProject.Tests/JsonData/emptyAppsettings.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"AppSettings" :
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"AppSettings" :
|
"AppSettings" :
|
||||||
{
|
{
|
||||||
"Settings": {
|
"Settings": {
|
||||||
"Name": "BasicDotnetTemplate",
|
"Name": "MainProject",
|
||||||
"Version": "v1.0",
|
"Version": "v1.0",
|
||||||
"Description": "This template contains basic configuration for a .Net 8 backend"
|
"Description": "This template contains basic configuration for a .Net 8 backend"
|
||||||
},
|
},
|
||||||
16
MainProject.Tests/JsonData/noDbConfigurationAppSettings.json
Normal file
16
MainProject.Tests/JsonData/noDbConfigurationAppSettings.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"AppSettings" :
|
||||||
|
{
|
||||||
|
"Settings": {
|
||||||
|
"Name": "MainProject",
|
||||||
|
"Version": "v1.0",
|
||||||
|
"Description": "This template contains basic configuration for a .Net 8 backend"
|
||||||
|
},
|
||||||
|
"DatabaseSettings": {
|
||||||
|
"SqlServerConnectionString": "",
|
||||||
|
"MongoDbConnectionString": "",
|
||||||
|
"PostgreSQLConnectionString": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
MainProject.Tests/MainProject.Tests.csproj
Normal file
31
MainProject.Tests/MainProject.Tests.csproj
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MainProject\MainProject.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="JsonData/**" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
80
MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs
Normal file
80
MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using Microsoft.Extensions.DependencyModel.Resolution;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class ApiResponse_Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_OnlyStatus_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var baseResponse = new BaseResponse(200, null, null);
|
||||||
|
Assert.IsTrue(baseResponse.Status == 200 && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_OnlyStatus_IsInvalid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var baseResponse = new BaseResponse(201, null, null);
|
||||||
|
Assert.IsFalse(baseResponse.Status == 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_StatusAndMessage_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var baseResponse = new BaseResponse(200, "This is a test message", null);
|
||||||
|
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_AllFields_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
|
||||||
|
var baseResponse = new BaseResponse(200, "This is a test message", data);
|
||||||
|
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
98
MainProject.Tests/Models/Settings/Settings_Tests.cs
Normal file
98
MainProject.Tests/Models/Settings/Settings_Tests.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using Microsoft.Extensions.DependencyModel.Resolution;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Settings_Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiatePrivateSettings_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sqlServer = "Data Source=localhost; Initial Catalog=YourDatabase; User Id=YourUsername; Password=YourPassword;";
|
||||||
|
var mongodb = "mongodb://localhost:27017";
|
||||||
|
var postgres = "Server=localhost; Port=5432; Database=YourDatabase; User Id=YourUsername; Password=YourPassword;";
|
||||||
|
|
||||||
|
var privateSettings = new PrivateSettings()
|
||||||
|
{
|
||||||
|
DatabaseConnection = new DatabaseConnection() {
|
||||||
|
SqlServer = sqlServer,
|
||||||
|
Mongodb = mongodb,
|
||||||
|
Postgres = postgres,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.IsTrue(
|
||||||
|
privateSettings.DatabaseConnection != null &&
|
||||||
|
privateSettings.DatabaseConnection.SqlServer == sqlServer &&
|
||||||
|
privateSettings.DatabaseConnection.Mongodb == mongodb &&
|
||||||
|
privateSettings.DatabaseConnection.Postgres == postgres
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_OnlyStatus_IsInvalid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var baseResponse = new BaseResponse(201, null, null);
|
||||||
|
Assert.IsFalse(baseResponse.Status == 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_StatusAndMessage_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var baseResponse = new BaseResponse(200, "This is a test message", null);
|
||||||
|
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IstantiateBaseResponse_AllFields_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
|
||||||
|
var baseResponse = new BaseResponse(200, "This is a test message", data);
|
||||||
|
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
77
MainProject.Tests/Program_Tests.cs
Normal file
77
MainProject.Tests/Program_Tests.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class Program_Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Program_Configuration_IsValid()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var reflectionType = typeof(ReflectionProgram);
|
||||||
|
|
||||||
|
if (reflectionType != null)
|
||||||
|
{
|
||||||
|
MethodInfo[] methods = reflectionType.GetMethods(); //Using BindingFlags.NonPublic does not show any results
|
||||||
|
|
||||||
|
MethodInfo? execute = null;
|
||||||
|
|
||||||
|
foreach (MethodInfo m in methods)
|
||||||
|
{
|
||||||
|
if (m.Name == "LaunchConfiguration")
|
||||||
|
{
|
||||||
|
execute = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execute != null)
|
||||||
|
{
|
||||||
|
object? initializeObj = execute != null ? execute.Invoke(null, Array.Empty<object>()) : throw new ArgumentNullException("LaunchConfiguration not found");
|
||||||
|
MethodInfo? initialize = initializeObj != null ? (MethodInfo)initializeObj : throw new ArgumentNullException("Unable to convert object because execute.Invoke is null");
|
||||||
|
if (initialize != null)
|
||||||
|
{
|
||||||
|
var success = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
initialize.Invoke(null, new object[] { Array.Empty<string>() });
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (Exception innerException)
|
||||||
|
{
|
||||||
|
Assert.Fail($"An exception was thrown during initialize.Invoke: {innerException.Message}");
|
||||||
|
}
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail("Initialize is null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail("Initialize method not found in Program class.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail("Program class not found in the assembly.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
45
MainProject.Tests/TestsUtils/TestUtils.cs
Normal file
45
MainProject.Tests/TestsUtils/TestUtils.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using Microsoft.Extensions.DependencyModel.Resolution;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using BasicDotnetTemplate.MainProject.Utils;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Microsoft.OpenApi.Interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
public static class TestUtils
|
||||||
|
{
|
||||||
|
public static IConfiguration CreateConfiguration()
|
||||||
|
{
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
ProgramUtils.AddOpenApi(ref builder, appSettings);
|
||||||
|
AppSettings _appSettings = new AppSettings();
|
||||||
|
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
return builder.Configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IConfiguration CreateEmptyConfiguration(string? path = "", string? filename = "")
|
||||||
|
{
|
||||||
|
string appSettingsPath = String.IsNullOrEmpty(path) ? System.AppDomain.CurrentDomain.BaseDirectory : path;
|
||||||
|
return new ConfigurationBuilder()
|
||||||
|
.SetBasePath(appSettingsPath)
|
||||||
|
.AddJsonFile(String.IsNullOrEmpty(filename) ? "appsettings.json" : filename, optional: false, reloadOnChange: true)
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
325
MainProject.Tests/Utils/ProgramUtils_Tests.cs
Normal file
325
MainProject.Tests/Utils/ProgramUtils_Tests.cs
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using BasicDotnetTemplate.MainProject;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using Microsoft.Extensions.DependencyModel.Resolution;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using BasicDotnetTemplate.MainProject.Utils;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Microsoft.OpenApi.Interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class ProgramUtils_Tests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void NoOpenApiConfig_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
|
||||||
|
{
|
||||||
|
Title = "MainProject",
|
||||||
|
Description = "This template contains basic configuration for a .Net 8 backend",
|
||||||
|
Version = "v1.0",
|
||||||
|
Contact = null,
|
||||||
|
TermsOfService = null,
|
||||||
|
License = null,
|
||||||
|
Extensions = new Dictionary<string, IOpenApiExtension>()
|
||||||
|
};
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "noApiConfigurationAppSettings.json");
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(realAppSettings);
|
||||||
|
|
||||||
|
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
|
||||||
|
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
|
||||||
|
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
|
||||||
|
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
|
||||||
|
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
|
||||||
|
expectedOpenApiInfo.License == realOpenApiInfo.License;
|
||||||
|
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateOpenApiInfo_EmptyAppSettings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
|
||||||
|
{
|
||||||
|
Title = null,
|
||||||
|
Description = null,
|
||||||
|
Version = null,
|
||||||
|
Contact = null,
|
||||||
|
TermsOfService = null,
|
||||||
|
License = null,
|
||||||
|
Extensions = new Dictionary<string, IOpenApiExtension>()
|
||||||
|
};
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "emptyAppsettings.json");
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(realAppSettings);
|
||||||
|
|
||||||
|
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
|
||||||
|
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
|
||||||
|
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
|
||||||
|
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
|
||||||
|
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
|
||||||
|
expectedOpenApiInfo.License == realOpenApiInfo.License;
|
||||||
|
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateOpenApiInfo_NullSettings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
AppSettings appSettings = new AppSettings();
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
|
||||||
|
Assert.IsTrue(realOpenApiInfo != null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateOpenApiInfo_NullOpenApiSettings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
AppSettings appSettings = new AppSettings()
|
||||||
|
{
|
||||||
|
Settings = new Settings
|
||||||
|
{
|
||||||
|
Name = "Test",
|
||||||
|
Description = "This is a test description",
|
||||||
|
Version = "v1"
|
||||||
|
},
|
||||||
|
OpenApiSettings = null
|
||||||
|
};
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
|
||||||
|
Assert.IsTrue(realOpenApiInfo != null);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Title == appSettings.Settings.Name);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Description == appSettings.Settings.Description);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Version == appSettings.Settings.Version);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CreateOpenApiInfo_NullTermsOfServiceUrl()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AppSettings appSettings = new AppSettings()
|
||||||
|
{
|
||||||
|
Settings = new Settings
|
||||||
|
{
|
||||||
|
Name = "Test",
|
||||||
|
Description = "This is a test description",
|
||||||
|
Version = "v1"
|
||||||
|
},
|
||||||
|
OpenApiSettings = new OpenApiSettings
|
||||||
|
{
|
||||||
|
TermsOfServiceUrl = null,
|
||||||
|
OpenApiContact = null,
|
||||||
|
OpenApiLicense = null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
|
||||||
|
Assert.IsTrue(realOpenApiInfo != null);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Title == appSettings.Settings.Name);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Description == appSettings.Settings.Description);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.Version == appSettings.Settings.Version);
|
||||||
|
Assert.IsTrue(realOpenApiInfo.TermsOfService == null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void OpenApiConfig_NotNull()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
|
||||||
|
{
|
||||||
|
Title = "MainProject",
|
||||||
|
Description = "This template contains basic configuration for a .Net 8 backend",
|
||||||
|
Version = "v1.0",
|
||||||
|
Contact = null,
|
||||||
|
TermsOfService = null,
|
||||||
|
License = null,
|
||||||
|
Extensions = new Dictionary<string, IOpenApiExtension>()
|
||||||
|
};
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "completeAppSettings.json");
|
||||||
|
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
|
||||||
|
|
||||||
|
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
|
||||||
|
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
|
||||||
|
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
|
||||||
|
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
|
||||||
|
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
|
||||||
|
expectedOpenApiInfo.License == realOpenApiInfo.License;
|
||||||
|
|
||||||
|
Assert.IsFalse(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AddOpenApi_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
ProgramUtils.AddOpenApi(ref builder, appSettings);
|
||||||
|
AppSettings _appSettings = new AppSettings();
|
||||||
|
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
var areEquals = appSettings.OpenApiSettings?.OpenApiContact?.Name == _appSettings.OpenApiSettings?.OpenApiContact?.Name &&
|
||||||
|
appSettings.OpenApiSettings?.OpenApiContact?.Url == _appSettings.OpenApiSettings?.OpenApiContact?.Url &&
|
||||||
|
appSettings.OpenApiSettings?.OpenApiLicense?.Name == _appSettings.OpenApiSettings?.OpenApiLicense?.Name &&
|
||||||
|
appSettings.OpenApiSettings?.OpenApiLicense?.Url == _appSettings.OpenApiSettings?.OpenApiLicense?.Url &&
|
||||||
|
appSettings.OpenApiSettings?.TermsOfServiceUrl == _appSettings.OpenApiSettings?.TermsOfServiceUrl;
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AddSqlServerContext_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
ProgramUtils.AddDbContext(ref builder, appSettings);
|
||||||
|
AppSettings _appSettings = new AppSettings();
|
||||||
|
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
var areEquals = appSettings.DatabaseSettings?.SqlServerConnectionString == _appSettings.DatabaseSettings?.SqlServerConnectionString;
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AddMongoDbContext_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
ProgramUtils.AddDbContext(ref builder, appSettings);
|
||||||
|
AppSettings _appSettings = new AppSettings();
|
||||||
|
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
var areEquals = appSettings.DatabaseSettings?.MongoDbConnectionString == _appSettings.DatabaseSettings?.MongoDbConnectionString;
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AddPostgreSqlDbContext_Valid()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
|
||||||
|
ProgramUtils.AddDbContext(ref builder, appSettings);
|
||||||
|
AppSettings _appSettings = new AppSettings();
|
||||||
|
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
var areEquals = appSettings.DatabaseSettings?.PostgreSQLConnectionString == _appSettings.DatabaseSettings?.PostgreSQLConnectionString;
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void NoSqlServerContext_Empty()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DatabaseSettings expectedDbSettings = new DatabaseSettings()
|
||||||
|
{
|
||||||
|
SqlServerConnectionString = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
|
||||||
|
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "noApiConfigurationAppSettings.json");
|
||||||
|
ProgramUtils.AddDbContext(ref builder, realAppSettings);
|
||||||
|
|
||||||
|
var areEquals = expectedDbSettings.SqlServerConnectionString == realAppSettings.DatabaseSettings?.SqlServerConnectionString;
|
||||||
|
Console.WriteLine(realAppSettings.DatabaseSettings?.SqlServerConnectionString);
|
||||||
|
Assert.IsTrue(areEquals);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.InnerException);
|
||||||
|
Assert.Fail($"An exception was thrown: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
60
MainProject/Controllers/BaseController.cs
Normal file
60
MainProject/Controllers/BaseController.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Controllers
|
||||||
|
{
|
||||||
|
public abstract class BaseController : ControllerBase
|
||||||
|
{
|
||||||
|
protected readonly IConfiguration _configuration;
|
||||||
|
protected readonly AppSettings _appSettings;
|
||||||
|
|
||||||
|
protected BaseController(
|
||||||
|
IConfiguration configuration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_appSettings = new AppSettings();
|
||||||
|
_configuration.GetSection("AppSettings").Bind(_appSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
private static BaseResponse CreateResponse(HttpStatusCode status, string message, object? data = null)
|
||||||
|
{
|
||||||
|
return new BaseResponse((int)status, message, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected new IActionResult Created(string message, object? data = null)
|
||||||
|
{
|
||||||
|
message = String.IsNullOrEmpty(message) ? "Created" : message;
|
||||||
|
return StatusCode((int)HttpStatusCode.Created, CreateResponse(HttpStatusCode.Created, message, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IActionResult Success(string message, object? data = null)
|
||||||
|
{
|
||||||
|
message = String.IsNullOrEmpty(message) ? "Success" : message;
|
||||||
|
return StatusCode((int)HttpStatusCode.OK, CreateResponse(HttpStatusCode.OK, message, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IActionResult NotFound(string message, object? data = null)
|
||||||
|
{
|
||||||
|
message = String.IsNullOrEmpty(message) ? "Not found" : message;
|
||||||
|
return StatusCode((int)HttpStatusCode.NotFound, CreateResponse(HttpStatusCode.NotFound, message, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IActionResult BadRequest(string message, object? data = null)
|
||||||
|
{
|
||||||
|
message = String.IsNullOrEmpty(message) ? "Bad request" : message;
|
||||||
|
return StatusCode((int)HttpStatusCode.BadRequest, CreateResponse(HttpStatusCode.BadRequest, message, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IActionResult InternalServerError(string message)
|
||||||
|
{
|
||||||
|
message = String.IsNullOrEmpty(message) ? "Internal server error" : message;
|
||||||
|
return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
|
}
|
||||||
18
MainProject/Controllers/RootController.cs
Normal file
18
MainProject/Controllers/RootController.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Controllers
|
||||||
|
{
|
||||||
|
[Route("")]
|
||||||
|
public class RootController : ControllerBase
|
||||||
|
{
|
||||||
|
public RootController() { }
|
||||||
|
|
||||||
|
[HttpGet("")]
|
||||||
|
public IActionResult GetRoot()
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
MainProject/Controllers/VersionController.cs
Normal file
19
MainProject/Controllers/VersionController.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Controllers
|
||||||
|
{
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class VersionController : BaseController
|
||||||
|
{
|
||||||
|
public VersionController(
|
||||||
|
IConfiguration configuration
|
||||||
|
) : base(configuration) { }
|
||||||
|
|
||||||
|
[HttpGet("get")]
|
||||||
|
public IActionResult GetVersion()
|
||||||
|
{
|
||||||
|
return Success(String.Empty, _appSettings?.Settings?.Version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
MainProject/Core/Database/MongoDbContext.cs
Normal file
26
MainProject/Core/Database/MongoDbContext.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MongoDB.EntityFrameworkCore;
|
||||||
|
using MongoDB.EntityFrameworkCore.Extensions;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Database.Mongo;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Core.Database
|
||||||
|
{
|
||||||
|
public class MongoDbContext : DbContext
|
||||||
|
{
|
||||||
|
public MongoDbContext(DbContextOptions<MongoDbContext> options) : base(options) { }
|
||||||
|
|
||||||
|
public DbSet<Log> Logs { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Log>().ToCollection("Logs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
18
MainProject/Core/Database/PostgreSqlDbContext.cs
Normal file
18
MainProject/Core/Database/PostgreSqlDbContext.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Core.Database
|
||||||
|
{
|
||||||
|
public class PostgreSqlDbContext : DbContext
|
||||||
|
{
|
||||||
|
|
||||||
|
public PostgreSqlDbContext(DbContextOptions<PostgreSqlDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
20
MainProject/Core/Database/SqlServerContext.cs
Normal file
20
MainProject/Core/Database/SqlServerContext.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Core.Database
|
||||||
|
{
|
||||||
|
public class SqlServerContext : DbContext
|
||||||
|
{
|
||||||
|
|
||||||
|
public SqlServerContext(DbContextOptions<SqlServerContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<User> Users { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
44
MainProject/MainProject.csproj
Normal file
44
MainProject/MainProject.csproj
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="9.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
|
<PackageReference Include="MongoDB.Driver" Version="2.28.0" />
|
||||||
|
<PackageReference Include="MongoDB.EntityFrameworkCore" Version="8.1.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="NLog" Version="5.2.8" />
|
||||||
|
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
132
MainProject/Migrations/20240904211920_InitialCreate.Designer.cs
generated
Normal file
132
MainProject/Migrations/20240904211920_InitialCreate.Designer.cs
generated
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BasicDotnetTemplate.MainProject.Core.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SqlServerContext))]
|
||||||
|
[Migration("20240904211920_InitialCreate")]
|
||||||
|
partial class InitialCreate
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Role");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("RoleId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
79
MainProject/Migrations/20240904211920_InitialCreate.cs
Normal file
79
MainProject/Migrations/20240904211920_InitialCreate.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class InitialCreate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Role",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreationUserId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
UpdateUserId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
DeletionUserId = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Role", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Users",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
Username = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
FirstName = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
LastName = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
Email = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
RoleId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreationUserId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
UpdateUserId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
DeletionUserId = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Users", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Users_Role_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalTable: "Role",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Users_RoleId",
|
||||||
|
table: "Users",
|
||||||
|
column: "RoleId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Role");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
MainProject/Migrations/20241129231345_Try.Designer.cs
generated
Normal file
132
MainProject/Migrations/20241129231345_Try.Designer.cs
generated
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BasicDotnetTemplate.MainProject.Core.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SqlServerContext))]
|
||||||
|
[Migration("20241129231345_Try")]
|
||||||
|
partial class Try
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Role");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("RoleId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
MainProject/Migrations/20241129231345_Try.cs
Normal file
22
MainProject/Migrations/20241129231345_Try.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Try : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
MainProject/Migrations/SqlServerContextModelSnapshot.cs
Normal file
129
MainProject/Migrations/SqlServerContextModelSnapshot.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BasicDotnetTemplate.MainProject.Core.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MainProject.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SqlServerContext))]
|
||||||
|
partial class SqlServerContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Role");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("CreationUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("DeletionUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("RoleId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("UpdateUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
MainProject/Models/Api/Response/BaseResponse.cs
Normal file
19
MainProject/Models/Api/Response/BaseResponse.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Api.Response;
|
||||||
|
|
||||||
|
public class BaseResponse
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
public BaseResponse(int status, string? message, dynamic? data)
|
||||||
|
{
|
||||||
|
this.Status = status;
|
||||||
|
this.Message = message;
|
||||||
|
this.Data = data;
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
public int Status { get; set; }
|
||||||
|
#nullable enable
|
||||||
|
public string? Message { get; set; }
|
||||||
|
|
||||||
|
public virtual dynamic? Data { get; set; }
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
11
MainProject/Models/Database/Mongo/Log.cs
Normal file
11
MainProject/Models/Database/Mongo/Log.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Database.Mongo
|
||||||
|
{
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
public ObjectId Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
MainProject/Models/Database/SqlServer/Base.cs
Normal file
16
MainProject/Models/Database/SqlServer/Base.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer
|
||||||
|
{
|
||||||
|
public class Base
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public DateTime CreationTime { get; set; }
|
||||||
|
public int CreationUserId { get; set; }
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
public int UpdateUserId { get; set; }
|
||||||
|
public DateTime DeletionTime { get; set; }
|
||||||
|
public int DeletionUserId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
12
MainProject/Models/Database/SqlServer/Role.cs
Normal file
12
MainProject/Models/Database/SqlServer/Role.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer
|
||||||
|
{
|
||||||
|
public class Role : Base
|
||||||
|
{
|
||||||
|
public required string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
19
MainProject/Models/Database/SqlServer/User.cs
Normal file
19
MainProject/Models/Database/SqlServer/User.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer
|
||||||
|
{
|
||||||
|
public class User : Base
|
||||||
|
{
|
||||||
|
public required string Username { get; set; }
|
||||||
|
public required string FirstName { get; set; }
|
||||||
|
public required string LastName { get; set; }
|
||||||
|
public required string Email { get; set; }
|
||||||
|
public required Role Role { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public required string PasswordHash { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class AppSettings
|
public class AppSettings
|
||||||
{
|
{
|
||||||
@@ -6,6 +6,7 @@ public class AppSettings
|
|||||||
public Settings? Settings { get; set; }
|
public Settings? Settings { get; set; }
|
||||||
public PrivateSettings? PrivateSettings { get; set; }
|
public PrivateSettings? PrivateSettings { get; set; }
|
||||||
public OpenApiSettings? OpenApiSettings { get; set; }
|
public OpenApiSettings? OpenApiSettings { get; set; }
|
||||||
|
public DatabaseSettings? DatabaseSettings { get; set; }
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class DatabaseConnection
|
public class DatabaseConnection
|
||||||
{
|
{
|
||||||
10
MainProject/Models/Settings/DatabaseSettings.cs
Normal file
10
MainProject/Models/Settings/DatabaseSettings.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
public class DatabaseSettings
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
public string? SqlServerConnectionString { get; set; }
|
||||||
|
public string? MongoDbConnectionString { get; set; }
|
||||||
|
public string? PostgreSQLConnectionString { get; set; }
|
||||||
|
#nullable disable
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class OpenApiSettings
|
public class OpenApiSettings
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class OpenApiSettingsDetails
|
public class OpenApiSettingsDetails
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class PrivateSettings
|
public class PrivateSettings
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace BasicDotnetTemplate.Models.Settings;
|
namespace BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
public class Settings
|
public class Settings
|
||||||
{
|
{
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
<targets>
|
<targets>
|
||||||
<target name="logfile" xsi:type="File" fileName="file.txt" />
|
<target name="logfile" xsi:type="File" fileName="Logs/application.txt" />
|
||||||
<target name="logconsole" xsi:type="Console" />
|
<target name="logconsole" xsi:type="Console" />
|
||||||
</targets>
|
</targets>
|
||||||
|
|
||||||
61
MainProject/Program.cs
Normal file
61
MainProject/Program.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using NLog;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
using System.Reflection;
|
||||||
|
using BasicDotnetTemplate.MainProject.Utils;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject;
|
||||||
|
|
||||||
|
public static class ReflectionProgram
|
||||||
|
{
|
||||||
|
public static MethodInfo LaunchConfiguration()
|
||||||
|
{
|
||||||
|
var a = typeof(Program);
|
||||||
|
|
||||||
|
MethodInfo[] methods = a.GetMethods(); //Using BindingFlags.NonPublic does not show any results
|
||||||
|
MethodInfo? initialize = null;
|
||||||
|
|
||||||
|
foreach (MethodInfo m in methods)
|
||||||
|
{
|
||||||
|
if (m.Name == "Initialize")
|
||||||
|
{
|
||||||
|
initialize = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return initialize!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
|
public static WebApplication Initialize(string[] args)
|
||||||
|
{
|
||||||
|
Logger.Info("[Program][Initialize] Start building");
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder);
|
||||||
|
ProgramUtils.AddServices(ref builder);
|
||||||
|
ProgramUtils.AddScopes(ref builder);
|
||||||
|
ProgramUtils.AddOpenApi(ref builder, appSettings);
|
||||||
|
ProgramUtils.AddDbContext(ref builder, appSettings);
|
||||||
|
WebApplication app = builder.Build();
|
||||||
|
ProgramUtils.AddMiddlewares(ref app);
|
||||||
|
|
||||||
|
Logger.Info("[Program][Initialize] End building");
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
WebApplication app = Initialize(args);
|
||||||
|
Logger.Info("[Program][Main] Launching app");
|
||||||
|
app.Run();
|
||||||
|
NLog.LogManager.Shutdown(); // Flush and close down internal threads and timers
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
178
MainProject/Utils/ProgramUtils.cs
Normal file
178
MainProject/Utils/ProgramUtils.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using NLog;
|
||||||
|
using BasicDotnetTemplate.MainProject.Core.Database;
|
||||||
|
using BasicDotnetTemplate.MainProject.Models.Settings;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace BasicDotnetTemplate.MainProject.Utils;
|
||||||
|
|
||||||
|
public static class ProgramUtils
|
||||||
|
{
|
||||||
|
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public static AppSettings AddConfiguration(ref WebApplicationBuilder builder, string? path = "", string? filename = "")
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddConfiguration] Adding configuration");
|
||||||
|
|
||||||
|
string appSettingsPath = String.IsNullOrEmpty(path) ? System.AppDomain.CurrentDomain.BaseDirectory : path;
|
||||||
|
var _configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(appSettingsPath)
|
||||||
|
.AddJsonFile(String.IsNullOrEmpty(filename) ? "appsettings.json" : filename, optional: false, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IConfiguration>(_configuration);
|
||||||
|
|
||||||
|
PrivateSettings privateSettings = new PrivateSettings();
|
||||||
|
_configuration.GetSection("PrivateSettings").Bind(privateSettings);
|
||||||
|
|
||||||
|
AppSettings appSettings = new AppSettings();
|
||||||
|
appSettings.PrivateSettings = privateSettings;
|
||||||
|
_configuration.GetSection("AppSettings").Bind(appSettings);
|
||||||
|
|
||||||
|
builder.Services.Configure<AppSettings>(_configuration.GetSection("AppSettings"));
|
||||||
|
builder.Services.Configure<PrivateSettings>(_configuration.GetSection("PrivateSettings"));
|
||||||
|
|
||||||
|
Logger.Info("[ProgramUtils][AddConfiguration] Ended configuration");
|
||||||
|
|
||||||
|
return appSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpenApiInfo CreateOpenApiInfo(AppSettings appSettings)
|
||||||
|
{
|
||||||
|
OpenApiInfo openApiInfo = new OpenApiInfo
|
||||||
|
{
|
||||||
|
Version = appSettings.Settings?.Version,
|
||||||
|
Title = appSettings.Settings?.Name,
|
||||||
|
Description = appSettings.Settings?.Description
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.OpenApiSettings?.TermsOfServiceUrl))
|
||||||
|
{
|
||||||
|
openApiInfo.TermsOfService = new Uri(appSettings.OpenApiSettings.TermsOfServiceUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.OpenApiSettings?.OpenApiContact?.Name) && !String.IsNullOrEmpty(appSettings.OpenApiSettings?.OpenApiContact?.Url))
|
||||||
|
{
|
||||||
|
openApiInfo.Contact = new OpenApiContact
|
||||||
|
{
|
||||||
|
Name = appSettings.OpenApiSettings.OpenApiContact.Name,
|
||||||
|
Url = new Uri(appSettings.OpenApiSettings.OpenApiContact.Url)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.OpenApiSettings?.OpenApiLicense?.Name) && !String.IsNullOrEmpty(appSettings.OpenApiSettings?.OpenApiLicense?.Url))
|
||||||
|
{
|
||||||
|
openApiInfo.License = new OpenApiLicense
|
||||||
|
{
|
||||||
|
Name = appSettings.OpenApiSettings.OpenApiLicense.Name,
|
||||||
|
Url = new Uri(appSettings.OpenApiSettings.OpenApiLicense.Url)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return openApiInfo;
|
||||||
|
}
|
||||||
|
public static void AddOpenApi(ref WebApplicationBuilder builder, AppSettings appSettings)
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddOpenApi] Adding swagger doc");
|
||||||
|
|
||||||
|
builder.Services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.SwaggerDoc("v1", CreateOpenApiInfo(appSettings));
|
||||||
|
});
|
||||||
|
|
||||||
|
Logger.Info("[ProgramUtils][AddOpenApi] Ended swagger doc");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddServices(ref WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddServices] Adding services");
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication();
|
||||||
|
builder.Services.AddAuthorization();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
|
||||||
|
Logger.Info("[ProgramUtils][AddServices] Done services");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddMiddlewares(ref WebApplication app)
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddMiddlewares] Adding middlewares");
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
app.MapControllers(); // This maps all controllers
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseStaticFiles();
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(options =>
|
||||||
|
{
|
||||||
|
options.InjectStylesheet("/swagger-ui/custom.css");
|
||||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info("[ProgramUtils][AddMiddlewares] Done middlewares");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddDbContext(ref WebApplicationBuilder builder, AppSettings appSettings)
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddDbContext] Adding DbContext");
|
||||||
|
var messages = String.Empty;
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.DatabaseSettings?.SqlServerConnectionString))
|
||||||
|
{
|
||||||
|
var connectionString = appSettings.DatabaseSettings?.SqlServerConnectionString ?? String.Empty;
|
||||||
|
connectionString = connectionString.Replace("SQLSERVER_DB_SERVER", Environment.GetEnvironmentVariable("SQLSERVER_DB_SERVER"));
|
||||||
|
builder.Services.AddDbContext<SqlServerContext>(options =>
|
||||||
|
options.UseSqlServer(connectionString)
|
||||||
|
);
|
||||||
|
messages = "SqlServerContext";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.DatabaseSettings?.MongoDbConnectionString))
|
||||||
|
{
|
||||||
|
var connectionString = appSettings.DatabaseSettings?.MongoDbConnectionString ?? String.Empty;
|
||||||
|
connectionString = connectionString.Replace("MONGO_DB_SERVER", Environment.GetEnvironmentVariable("MONGODB_DB_SERVER"));
|
||||||
|
var databaseName = connectionString.Split("/").LastOrDefault();
|
||||||
|
if (!String.IsNullOrEmpty(databaseName))
|
||||||
|
{
|
||||||
|
var client = new MongoClient(connectionString);
|
||||||
|
builder.Services.AddDbContext<MongoDbContext>(options =>
|
||||||
|
options.UseMongoDB(client, databaseName)
|
||||||
|
);
|
||||||
|
messages = messages + (String.IsNullOrEmpty(messages) ? "" : ", ") + "MongoDbContext";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(appSettings.DatabaseSettings?.PostgreSQLConnectionString))
|
||||||
|
{
|
||||||
|
var connectionString = appSettings.DatabaseSettings?.PostgreSQLConnectionString ?? String.Empty;
|
||||||
|
connectionString = connectionString.Replace("POSTGRESQL_DB_SERVER", Environment.GetEnvironmentVariable("POSTGRESQL_DB_SERVER"));
|
||||||
|
builder.Services.AddDbContext<PostgreSqlDbContext>(options =>
|
||||||
|
options.UseNpgsql(connectionString)
|
||||||
|
);
|
||||||
|
messages = messages + (String.IsNullOrEmpty(messages) ? "" : ", ") + "PostgreSqlDbContext";
|
||||||
|
}
|
||||||
|
messages = String.IsNullOrEmpty(messages) ? "No context" : messages;
|
||||||
|
Logger.Info($"[ProgramUtils][AddDbContext] {messages} added");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddScopes(ref WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
Logger.Info("[ProgramUtils][AddScopes] Adding scopes");
|
||||||
|
Logger.Info("[ProgramUtils][AddScopes] Done scopes");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
MainProject/appsettings.json
Normal file
32
MainProject/appsettings.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"AppSettings" :
|
||||||
|
{
|
||||||
|
"Settings": {
|
||||||
|
"Name": "MainProject",
|
||||||
|
"Version": "v1.0",
|
||||||
|
"Description": "This template contains basic configuration for a .Net 8 backend"
|
||||||
|
},
|
||||||
|
"DatabaseSettings": {
|
||||||
|
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
|
||||||
|
"MongoDbConnectionString": "MONGO_DB_SERVER",
|
||||||
|
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
|
||||||
|
},
|
||||||
|
"OpenApiSettings": {
|
||||||
|
"TermsOfServiceUrl": "",
|
||||||
|
"OpenApiContact": {
|
||||||
|
"Name": "",
|
||||||
|
"Url": ""
|
||||||
|
},
|
||||||
|
"OpenApiLicense": {
|
||||||
|
"Name": "MIT License",
|
||||||
|
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
.topbar-wrapper img[alt="Swagger UI"], .topbar-wrapper span {
|
/* .topbar-wrapper img[alt="Swagger UI"], .topbar-wrapper span {
|
||||||
src
|
src
|
||||||
}
|
} */
|
||||||
|
|
||||||
.topbar-wrapper .link:after {
|
.topbar-wrapper .link:after {
|
||||||
/* content: 'Unoffical McLaren F1 API'; */
|
|
||||||
/* color: #fff; */
|
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
104
Program.cs
104
Program.cs
@@ -1,104 +0,0 @@
|
|||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using BasicDotnetTemplate.Models.Settings;
|
|
||||||
|
|
||||||
namespace BasicDotnetTemplate;
|
|
||||||
internal static class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
var _configuration = new ConfigurationBuilder()
|
|
||||||
.SetBasePath(Directory.GetCurrentDirectory())
|
|
||||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
|
||||||
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
|
|
||||||
.AddEnvironmentVariables()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// REGISTER SERVICES HERE
|
|
||||||
builder.Services.AddSingleton<IConfiguration>(_configuration);
|
|
||||||
|
|
||||||
PrivateSettings privateSettings = new PrivateSettings();
|
|
||||||
_configuration.GetSection("PrivateSettings").Bind(privateSettings);
|
|
||||||
|
|
||||||
builder.Services.Configure<AppSettings>(_configuration.GetSection("AppSettings"));
|
|
||||||
builder.Services.Configure<PrivateSettings>(_configuration.GetSection("PrivateSettings"));
|
|
||||||
|
|
||||||
builder.Services.AddAuthentication();
|
|
||||||
builder.Services.AddAuthorization();
|
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
|
||||||
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
|
||||||
|
|
||||||
AppSettings appSettings = new AppSettings();
|
|
||||||
appSettings.PrivateSettings = privateSettings;
|
|
||||||
_configuration.GetSection("AppSettings").Bind(appSettings);
|
|
||||||
|
|
||||||
OpenApiInfo openApiInfo = new()
|
|
||||||
{
|
|
||||||
Version = appSettings?.Settings?.Version,
|
|
||||||
Title = appSettings?.Settings?.Name,
|
|
||||||
Description = appSettings?.Settings?.Description
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(appSettings?.OpenApiSettings?.TermsOfServiceUrl))
|
|
||||||
{
|
|
||||||
openApiInfo.TermsOfService = new Uri(appSettings.OpenApiSettings.TermsOfServiceUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(appSettings?.OpenApiSettings?.OpenApiContact?.Name) && !String.IsNullOrEmpty(appSettings?.OpenApiSettings?.OpenApiContact?.Url))
|
|
||||||
{
|
|
||||||
openApiInfo.Contact = new OpenApiContact
|
|
||||||
{
|
|
||||||
Name = appSettings.OpenApiSettings.OpenApiContact.Name,
|
|
||||||
Url = new Uri(appSettings.OpenApiSettings.OpenApiContact.Url)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(appSettings?.OpenApiSettings?.OpenApiLicense?.Name) && !String.IsNullOrEmpty(appSettings?.OpenApiSettings?.OpenApiLicense?.Url))
|
|
||||||
{
|
|
||||||
openApiInfo.License = new OpenApiLicense
|
|
||||||
{
|
|
||||||
Name = appSettings.OpenApiSettings.OpenApiLicense.Name,
|
|
||||||
Url = new Uri(appSettings.OpenApiSettings.OpenApiLicense.Url)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Services.AddSwaggerGen(options =>
|
|
||||||
{
|
|
||||||
options.SwaggerDoc("v1", openApiInfo);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// REGISTER MIDDLEWARE HERE
|
|
||||||
app.UseAuthentication();
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
|
||||||
app.UseStaticFiles();
|
|
||||||
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.MapControllerRoute(
|
|
||||||
name: "default",
|
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseStaticFiles();
|
|
||||||
app.UseSwagger();
|
|
||||||
app.UseSwaggerUI(options =>
|
|
||||||
{
|
|
||||||
options.InjectStylesheet("/swagger-ui/custom.css");
|
|
||||||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
app.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
68
README.md
68
README.md
@@ -1,3 +1,69 @@
|
|||||||
# BasicDotnetTemplate
|
# MainProject
|
||||||
|
## Table of contents
|
||||||
|
- [MainProject](#mainproject)
|
||||||
|
- [Table of contents](#table-of-contents)
|
||||||
|
- [What is BasicDotnetTemplate?](#what-is-basicdotnettemplate)
|
||||||
|
- [Technologies](#technologies)
|
||||||
|
- [Dotnet](#dotnet)
|
||||||
|
- [Commands](#commands)
|
||||||
|
- [Debug](#debug)
|
||||||
|
- [Entity Framework](#entity-framework)
|
||||||
|
- [Sonarcloud](#sonarcloud)
|
||||||
|
- [Quality gate](#quality-gate)
|
||||||
|
- [Code smells](#code-smells)
|
||||||
|
|
||||||
|
## What is BasicDotnetTemplate?
|
||||||
|
BasicDotnetTemplate is a basic project written in .NET 8. It contains MainProject, a WebApi project, and MainProject.Tests written in .NET 8 that contains tests for MainProject.
|
||||||
|
|
||||||
|
## Technologies
|
||||||
|
### Dotnet
|
||||||
|
[](https://dotnet.microsoft.com/en-us)
|
||||||
|
|
||||||
|
Every component is developed using **dotnet-core 8.0.201** and was generated with [dotnet](https://dotnet.microsoft.com/).
|
||||||
|
|
||||||
|
> .NET is the free, open-source, cross-platform framework for building modern apps and powerful cloud services. Supported on Windows, Linux, and macOS.
|
||||||
|
|
||||||
|
#### Commands
|
||||||
|
##### Debug
|
||||||
|
You can use the following comands in the MainProject folder.
|
||||||
|
```bash
|
||||||
|
dotnet watch run
|
||||||
|
```
|
||||||
|
Restarts or hot reloads the specified application, or runs a specified dotnet command, when changes in source code are detected.
|
||||||
|
|
||||||
|
### Entity Framework
|
||||||
|
This project uses Entity Framework Core, you can find the official documentation [here](https://www.entityframeworktutorial.net/efcore/entity-framework-core.aspx).
|
||||||
|
> Entity Framework is an Object/Relational Mapping (O/RM) framework. It is an enhancement to ADO.NET that gives developers an automated mechanism for accessing & storing the data in the database.
|
||||||
|
> EF Core supports two development approaches 1) Code-First 2) Database-First.
|
||||||
|
> In the code-first approach, EF Core API creates the database and tables using migration based on the conventions and configuration provided in your domain classes. This approach is useful in Domain Driven Design (DDD).
|
||||||
|
|
||||||
|
### Sonarcloud
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate)
|
||||||
|
|
||||||
|
This project is scanned on [SonarCloud](https://www.sonarsource.com/lp/products/sonarcloud/), a powerful cloud-based code analysis service designed to detect coding issues. It works with GitHub, Bitbucket Cloud, Azure DevOps and GitLab.
|
||||||
|
You can find the integration in [build.yml](.github/workflows/build.yml).
|
||||||
|
|
||||||
|
#### Quality gate
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate)
|
||||||
|
|
||||||
|
A Quality Gate is a set of measure-based, Boolean conditions. It helps you know immediately whether your projects are production-ready.
|
||||||
|
This project uses **Sonar way** quality gate:
|
||||||
|
|
||||||
|
| Condition | Metric and rating | Real rating |
|
||||||
|
| ----------- | ----------- | ----------- |
|
||||||
|
| No new bugs are introduced | Reliability rating is A | [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) |
|
||||||
|
| No new vulnerabilities are introduced | Security rating is A | [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) |
|
||||||
|
| New code has limited technical debt | Maintainability rating is A | [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) |
|
||||||
|
| All new security hotspots are reviewed | | |
|
||||||
|
| New code is sufficiently covered by test | Coverage is greater than or equal to 80.0% | [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) |
|
||||||
|
| New code has limited duplication | Duplicated Lines (%) is less than or equal to 3.0% | [](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate) |
|
||||||
|
|
||||||
|
##### Code smells
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=csimonapastore_BasicDotnetTemplate)
|
||||||
|
|
||||||
|
> One way to look at smells is with respect to principles and quality: "Smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality".[Suryanarayana, Girish (November 2014). Refactoring for Software Design Smells. Morgan Kaufmann.]
|
||||||
|
> Code smells are usually not bugs; they are not technically incorrect and do not prevent the program from functioning. Instead, they indicate weaknesses in design that may slow down development or increase the risk of bugs or failures in the future. Bad code smells can be an indicator of factors that contribute to technical debt.[Tufano, Michele; Palomba, Fabio; Bavota, Gabriele; Oliveto, Rocco; Di Penta, Massimiliano; De Lucia, Andrea; Poshyvanyk, Denys (2015).] Robert C. Martin calls a list of code smells a "value system" for software craftsmanship.[Martin, Robert C. (2009). "17: Smells and Heuristics". Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall.]
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user