├── .gitignore ├── SixAPI ├── Binders │ └── PlatformModelBinder.cs ├── Controllers │ ├── CommandsController.cs │ ├── PlatformsController.cs │ └── TestAsyncActionFilter.cs ├── Data │ ├── AppDbContext.cs │ ├── CommandRepo.cs │ └── ICommandRepo.cs ├── Dtos │ ├── CommandCreateDto.cs │ ├── CommandReadDto.cs │ ├── CommandUpdateDto.cs │ └── PlatformCreateDto.cs ├── Migrations │ ├── 20220428004042_InitialMigration.Designer.cs │ ├── 20220428004042_InitialMigration.cs │ ├── 20220518060742_add-platforms.Designer.cs │ ├── 20220518060742_add-platforms.cs │ └── AppDbContextModelSnapshot.cs ├── Models │ ├── Command.cs │ └── Platform.cs ├── Profiles │ ├── CommandsProfile.cs │ └── PlatformsProfile.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── SixAPI.csproj ├── appsettings.Development.json ├── appsettings.json └── docker-compose.yaml └── SixMinApi ├── Data ├── AppDbContext.cs ├── CommandRepo.cs └── ICommandRepo.cs ├── Dtos ├── CommandCreateDto.cs ├── CommandReadDto.cs └── CommandUpdateDto.cs ├── Migrations ├── 20220522055326_initialmigration.Designer.cs ├── 20220522055326_initialmigration.cs └── AppDbContextModelSnapshot.cs ├── Models └── Command.cs ├── Profiles └── CommandsProfile.cs ├── Program.cs ├── Properties └── launchSettings.json ├── SixMinApi.csproj ├── appsettings.Development.json ├── appsettings.json └── docker-compose.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Skip to content 3 | Pull requests 4 | Issues 5 | Marketplace 6 | Explore 7 | @binarythistle 8 | Dotnet-Playbook / 9 | S04E03---Running-.Net-Microservices-in-Kubernetes 10 | Private 11 | 12 | Code 13 | Issues 14 | Pull requests 15 | Actions 16 | Projects 17 | Security 18 | Insights 19 | 20 | Settings 21 | 22 | S04E03---Running-.Net-Microservices-in-Kubernetes/.gitignore 23 | @binarythistle 24 | binarythistle updated readme and .gitignore 25 | Latest commit b57f5d9 on 15 Jul 2021 26 | History 27 | 1 contributor 28 | 352 lines (283 sloc) 5.87 KB 29 | ## Ignore Visual Studio temporary files, build results, and 30 | ## files generated by popular Visual Studio add-ons. 31 | ## 32 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 33 | 34 | # User-specific files 35 | *.rsuser 36 | *.suo 37 | *.user 38 | *.userosscache 39 | *.sln.docstates 40 | 41 | # User-specific files (MonoDevelop/Xamarin Studio) 42 | *.userprefs 43 | 44 | # Mono auto generated files 45 | mono_crash.* 46 | 47 | # Build results 48 | [Dd]ebug/ 49 | [Dd]ebugPublic/ 50 | [Rr]elease/ 51 | [Rr]eleases/ 52 | x64/ 53 | x86/ 54 | [Aa][Rr][Mm]/ 55 | [Aa][Rr][Mm]64/ 56 | bld/ 57 | [Bb]in/ 58 | [Oo]bj/ 59 | [Ll]og/ 60 | [Ll]ogs/ 61 | 62 | # Visual Studio 2015/2017 cache/options directory 63 | .vs/ 64 | # Uncomment if you have tasks that create the project's static files in wwwroot 65 | #wwwroot/ 66 | .vscode 67 | 68 | 69 | # Visual Studio 2017 auto generated files 70 | Generated\ Files/ 71 | 72 | # MSTest test Results 73 | [Tt]est[Rr]esult*/ 74 | [Bb]uild[Ll]og.* 75 | 76 | # NUnit 77 | *.VisualState.xml 78 | TestResult.xml 79 | nunit-*.xml 80 | 81 | # Build Results of an ATL Project 82 | [Dd]ebugPS/ 83 | [Rr]eleasePS/ 84 | dlldata.c 85 | 86 | # Benchmark Results 87 | BenchmarkDotNet.Artifacts/ 88 | 89 | # .NET Core 90 | project.lock.json 91 | project.fragment.lock.json 92 | artifacts/ 93 | 94 | # StyleCop 95 | StyleCopReport.xml 96 | 97 | # Files built by Visual Studio 98 | *_i.c 99 | *_p.c 100 | *_h.h 101 | *.ilk 102 | *.meta 103 | *.obj 104 | *.iobj 105 | *.pch 106 | *.pdb 107 | *.ipdb 108 | *.pgc 109 | *.pgd 110 | *.rsp 111 | *.sbr 112 | *.tlb 113 | *.tli 114 | *.tlh 115 | *.tmp 116 | *.tmp_proj 117 | *_wpftmp.csproj 118 | *.log 119 | *.vspscc 120 | *.vssscc 121 | .builds 122 | *.pidb 123 | *.svclog 124 | *.scc 125 | 126 | # Chutzpah Test files 127 | _Chutzpah* 128 | 129 | # Visual C++ cache files 130 | ipch/ 131 | *.aps 132 | *.ncb 133 | *.opendb 134 | *.opensdf 135 | *.sdf 136 | *.cachefile 137 | *.VC.db 138 | *.VC.VC.opendb 139 | 140 | # Visual Studio profiler 141 | *.psess 142 | *.vsp 143 | *.vspx 144 | *.sap 145 | 146 | # Visual Studio Trace Files 147 | *.e2e 148 | 149 | # TFS 2012 Local Workspace 150 | $tf/ 151 | 152 | # Guidance Automation Toolkit 153 | *.gpState 154 | 155 | # ReSharper is a .NET coding add-in 156 | _ReSharper*/ 157 | *.[Rr]e[Ss]harper 158 | *.DotSettings.user 159 | 160 | # TeamCity is a build add-in 161 | _TeamCity* 162 | 163 | # DotCover is a Code Coverage Tool 164 | *.dotCover 165 | 166 | # AxoCover is a Code Coverage Tool 167 | .axoCover/* 168 | !.axoCover/settings.json 169 | 170 | # Visual Studio code coverage results 171 | *.coverage 172 | *.coveragexml 173 | 174 | # NCrunch 175 | _NCrunch_* 176 | .*crunch*.local.xml 177 | nCrunchTemp_* 178 | 179 | # MightyMoose 180 | *.mm.* 181 | AutoTest.Net/ 182 | 183 | # Web workbench (sass) 184 | .sass-cache/ 185 | 186 | # Installshield output folder 187 | [Ee]xpress/ 188 | 189 | # DocProject is a documentation generator add-in 190 | DocProject/buildhelp/ 191 | DocProject/Help/*.HxT 192 | DocProject/Help/*.HxC 193 | DocProject/Help/*.hhc 194 | DocProject/Help/*.hhk 195 | DocProject/Help/*.hhp 196 | DocProject/Help/Html2 197 | DocProject/Help/html 198 | 199 | # Click-Once directory 200 | publish/ 201 | 202 | # Publish Web Output 203 | *.[Pp]ublish.xml 204 | *.azurePubxml 205 | # Note: Comment the next line if you want to checkin your web deploy settings, 206 | # but database connection strings (with potential passwords) will be unencrypted 207 | *.pubxml 208 | *.publishproj 209 | 210 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 211 | # checkin your Azure Web App publish settings, but sensitive information contained 212 | # in these scripts will be unencrypted 213 | PublishScripts/ 214 | 215 | # NuGet Packages 216 | *.nupkg 217 | # NuGet Symbol Packages 218 | *.snupkg 219 | # The packages folder can be ignored because of Package Restore 220 | **/[Pp]ackages/* 221 | # except build/, which is used as an MSBuild target. 222 | !**/[Pp]ackages/build/ 223 | # Uncomment if necessary however generally it will be regenerated when needed 224 | #!**/[Pp]ackages/repositories.config 225 | # NuGet v3's project.json files produces more ignorable files 226 | *.nuget.props 227 | *.nuget.targets 228 | 229 | # Microsoft Azure Build Output 230 | csx/ 231 | *.build.csdef 232 | 233 | # Microsoft Azure Emulator 234 | ecf/ 235 | rcf/ 236 | 237 | # Windows Store app package directories and files 238 | AppPackages/ 239 | BundleArtifacts/ 240 | Package.StoreAssociation.xml 241 | _pkginfo.txt 242 | *.appx 243 | *.appxbundle 244 | *.appxupload 245 | 246 | # Visual Studio cache files 247 | # files ending in .cache can be ignored 248 | *.[Cc]ache 249 | # but keep track of directories ending in .cache 250 | !?*.[Cc]ache/ 251 | 252 | # Others 253 | ClientBin/ 254 | ~$* 255 | *~ 256 | *.dbmdl 257 | *.dbproj.schemaview 258 | *.jfm 259 | *.pfx 260 | *.publishsettings 261 | orleans.codegen.cs 262 | 263 | # Including strong name files can present a security risk 264 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 265 | #*.snk 266 | 267 | # Since there are multiple workflows, uncomment next line to ignore bower_components 268 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 269 | #bower_components/ 270 | 271 | # RIA/Silverlight projects 272 | Generated_Code/ 273 | 274 | # Backup & report files from converting an old project file 275 | # to a newer Visual Studio version. Backup files are not needed, 276 | # because we have git ;-) 277 | _UpgradeReport_Files/ 278 | Backup*/ 279 | UpgradeLog*.XML 280 | UpgradeLog*.htm 281 | ServiceFabricBackup/ 282 | *.rptproj.bak 283 | 284 | # SQL Server files 285 | *.mdf 286 | *.ldf 287 | *.ndf 288 | 289 | # Business Intelligence projects 290 | *.rdl.data 291 | *.bim.layout 292 | *.bim_*.settings 293 | *.rptproj.rsuser 294 | *- [Bb]ackup.rdl 295 | *- [Bb]ackup ([0-9]).rdl 296 | *- [Bb]ackup ([0-9][0-9]).rdl 297 | 298 | # Microsoft Fakes 299 | FakesAssemblies/ 300 | 301 | # GhostDoc plugin setting file 302 | *.GhostDoc.xml 303 | 304 | # Node.js Tools for Visual Studio 305 | .ntvs_analysis.dat 306 | node_modules/ 307 | 308 | # Visual Studio 6 build log 309 | *.plg 310 | 311 | # Visual Studio 6 workspace options file 312 | *.opt 313 | 314 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 315 | *.vbw 316 | 317 | # Visual Studio LightSwitch build output 318 | **/*.HTMLClient/GeneratedArtifacts 319 | **/*.DesktopClient/GeneratedArtifacts 320 | **/*.DesktopClient/ModelManifest.xml 321 | **/*.Server/GeneratedArtifacts 322 | **/*.Server/ModelManifest.xml 323 | _Pvt_Extensions 324 | 325 | # Paket dependency manager 326 | .paket/paket.exe 327 | paket-files/ 328 | 329 | # FAKE - F# Make 330 | .fake/ 331 | 332 | # CodeRush personal settings 333 | .cr/personal 334 | 335 | # Python Tools for Visual Studio (PTVS) 336 | __pycache__/ 337 | *.pyc 338 | 339 | # Cake - Uncomment if you are using it 340 | # tools/** 341 | # !tools/packages.config 342 | 343 | # Tabs Studio 344 | *.tss 345 | 346 | # Telerik's JustMock configuration file 347 | *.jmconfig 348 | 349 | # BizTalk build output 350 | *.btp.cs 351 | *.btm.cs 352 | *.odx.cs 353 | *.xsd.cs 354 | 355 | # OpenCover UI analysis results 356 | OpenCover/ 357 | 358 | # Azure Stream Analytics local run output 359 | ASALocalRun/ 360 | 361 | # MSBuild Binary and Structured Log 362 | *.binlog 363 | 364 | # NVidia Nsight GPU debugger configuration file 365 | *.nvuser 366 | 367 | # MFractors (Xamarin productivity tool) working folder 368 | .mfractor/ 369 | 370 | # Local History for Visual Studio 371 | .localhistory/ 372 | 373 | # BeatPulse healthcheck temp database 374 | healthchecksdb 375 | 376 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 377 | MigrationBackup/ 378 | 379 | # Ionide (cross platform F# VS Code tools) working folder 380 | .ionide/ 381 | 382 | © 2022 GitHub, Inc. 383 | 384 | Terms 385 | Privacy 386 | Security 387 | Status 388 | Docs 389 | Contact GitHub 390 | Pricing 391 | API 392 | Training 393 | Blog 394 | About 395 | 396 | Loading complete -------------------------------------------------------------------------------- /SixAPI/Binders/PlatformModelBinder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ModelBinding; 2 | using SixAPI.Data; 3 | 4 | namespace SixAPI.Binders 5 | { 6 | public class PlatformModelBinder : IModelBinder 7 | { 8 | private readonly AppDbContext _context; 9 | 10 | public PlatformModelBinder(AppDbContext context) 11 | { 12 | _context = context; 13 | } 14 | 15 | public Task BindModelAsync(ModelBindingContext bindingContext) 16 | { 17 | if (bindingContext == null) 18 | { 19 | Console.WriteLine("--> Binding Context is Null"); 20 | throw new ArgumentNullException(nameof(bindingContext)); 21 | } 22 | 23 | 24 | var modelName = bindingContext.ModelName; 25 | 26 | Console.WriteLine($"--> modelName: {modelName}"); 27 | 28 | // Try to fetch the value of the argument by name 29 | var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); 30 | 31 | if (valueProviderResult == ValueProviderResult.None) 32 | { 33 | Console.WriteLine("--> ValueProviderResult is none"); 34 | return Task.CompletedTask; 35 | } 36 | 37 | bindingContext.ModelState.SetModelValue(modelName, valueProviderResult); 38 | 39 | var value = valueProviderResult.FirstValue; 40 | 41 | // Check if the argument value is null or empty 42 | if (string.IsNullOrEmpty(value)) 43 | { 44 | return Task.CompletedTask; 45 | } 46 | 47 | if (!int.TryParse(value, out var id)) 48 | { 49 | // Non-integer arguments result in model state errors 50 | bindingContext.ModelState.TryAddModelError( 51 | modelName, "Platform Id must be an integer."); 52 | 53 | return Task.CompletedTask; 54 | } 55 | 56 | // Model will be null if not found, including for 57 | // out of range id values (0, -3, etc.) 58 | var model = _context.Platforms.Find(id); 59 | bindingContext.Result = ModelBindingResult.Success(model); 60 | return Task.CompletedTask; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /SixAPI/Controllers/CommandsController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | using SixAPI.Models; 5 | using SixAPI.Dtos; 6 | using SixAPI.Data; 7 | using Microsoft.AspNetCore.JsonPatch; 8 | 9 | namespace SixAPI.Controllers 10 | { 11 | [ServiceFilter(typeof(TestAsyncActionFilter))] 12 | [Route("api/v1/[controller]")] 13 | [ApiController] 14 | public class CommandsController : ControllerBase 15 | { 16 | private readonly ICommandRepo _repo; 17 | private readonly IMapper _mapper; 18 | 19 | public CommandsController(ICommandRepo repo, IMapper mapper) 20 | { 21 | _repo = repo; 22 | _mapper = mapper; 23 | } 24 | 25 | [HttpGet] 26 | public async Task>> GetAllCommands([FromHeader] bool flipSwitch) 27 | { 28 | var commands = await _repo.GetAllCommands(); 29 | Console.ForegroundColor = ConsoleColor.Blue; 30 | Console.WriteLine($"--> The flip switch is: {flipSwitch}"); 31 | Console.ResetColor(); 32 | 33 | return Ok(_mapper.Map>(commands)); 34 | } 35 | 36 | [HttpGet("{id}", Name = "GetCommandById")] 37 | public async Task> GetCommandById(int id) 38 | { 39 | var commandModel = await _repo.GetCommandById(id); 40 | if (commandModel != null) 41 | { 42 | return Ok(_mapper.Map(commandModel)); 43 | } 44 | return NotFound(); 45 | } 46 | 47 | [HttpPost] 48 | public async Task> CreateCommand(CommandCreateDto cmdCreateDto) 49 | { 50 | var commandModel = _mapper.Map(cmdCreateDto); 51 | await _repo.CreateCommand(commandModel); 52 | await _repo.SaveChanges(); 53 | 54 | var cmdReadDto = _mapper.Map(commandModel); 55 | 56 | Console.WriteLine($"Model State is: {ModelState.IsValid}"); 57 | 58 | return CreatedAtRoute(nameof(GetCommandById), new { Id = cmdReadDto.Id}, cmdReadDto); 59 | } 60 | 61 | //PATCH api/v1/commands/{id} 62 | [HttpPatch("{id}")] 63 | public async Task PartialCommandUpdate(int id, JsonPatchDocument patchDoc) 64 | { 65 | var commandModelFromRepo = await _repo.GetCommandById(id); 66 | if(commandModelFromRepo == null) 67 | { 68 | return NotFound(); 69 | } 70 | 71 | var commandToPatch = _mapper.Map(commandModelFromRepo); 72 | patchDoc.ApplyTo(commandToPatch, ModelState); 73 | 74 | if(!TryValidateModel(commandToPatch)) 75 | { 76 | return ValidationProblem(ModelState); 77 | } 78 | 79 | _mapper.Map(commandToPatch, commandModelFromRepo); 80 | 81 | //await _repo.UpdateCommand(commandModelFromRepo); 82 | 83 | await _repo.SaveChanges(); 84 | 85 | return NoContent(); 86 | } 87 | 88 | //PUT api/commands/{id} 89 | [HttpPut("{id}")] 90 | public async Task UpdateCommand(int id, CommandUpdateDto commandUpdateDto) 91 | { 92 | var commandModelFromRepo = await _repo.GetCommandById(id); 93 | if(commandModelFromRepo == null) 94 | { 95 | return NotFound(); 96 | } 97 | _mapper.Map(commandUpdateDto, commandModelFromRepo); 98 | 99 | await _repo.SaveChanges(); 100 | 101 | return NoContent(); 102 | } 103 | 104 | //DELETE api/commands/{id} 105 | [HttpDelete("{id}")] 106 | public async Task DeleteCommand(int id) 107 | { 108 | var commandModelFromRepo = await _repo.GetCommandById(id); 109 | if(commandModelFromRepo == null) 110 | { 111 | return NotFound(); 112 | } 113 | _repo.DeleteCommand(commandModelFromRepo); 114 | await _repo.SaveChanges(); 115 | 116 | return NoContent(); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /SixAPI/Controllers/PlatformsController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using SixAPI.Models; 3 | 4 | namespace SixAPI.Controllers 5 | { 6 | [Route("api/v1/[controller]")] 7 | [ApiController] 8 | public class PlatformsController : ControllerBase 9 | { 10 | 11 | 12 | [HttpGet("binder/{id}")] 13 | public IActionResult GetPlatformById( 14 | [ModelBinder(Name = "id")] Platform platform) 15 | { 16 | if (platform == null) 17 | { 18 | return NotFound(); 19 | } 20 | 21 | return Ok(platform); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /SixAPI/Controllers/TestAsyncActionFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | 4 | namespace SixAPI.Controllers 5 | { 6 | public class TestAsyncActionFilter : IAsyncActionFilter 7 | { 8 | public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) 9 | { 10 | var qs = context.HttpContext.Request.QueryString; 11 | 12 | //var requestBody = context.HttpContext.Request.Body. 13 | Console.ForegroundColor = ConsoleColor.Red; 14 | Console.WriteLine("--> Action Filter doing something BEFORE the Action..."); 15 | Console.WriteLine($"--> Query string: {qs}"); 16 | 17 | var result = await next(); 18 | Console.ForegroundColor = ConsoleColor.Green; 19 | Console.WriteLine("--> Action Filter doing something AFTER the Action..."); 20 | Console.ResetColor(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /SixAPI/Data/AppDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using SixAPI.Models; 3 | 4 | namespace SixAPI.Data 5 | { 6 | public class AppDbContext : DbContext 7 | { 8 | public AppDbContext(DbContextOptions options) :base(options) 9 | { 10 | 11 | } 12 | 13 | public DbSet Commands => Set(); 14 | public DbSet Platforms => Set(); 15 | } 16 | } -------------------------------------------------------------------------------- /SixAPI/Data/CommandRepo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using SixAPI.Models; 3 | 4 | namespace SixAPI.Data 5 | { 6 | public class CommandRepo : ICommandRepo 7 | { 8 | private readonly AppDbContext _context; 9 | 10 | public CommandRepo(AppDbContext context) 11 | { 12 | _context = context; 13 | } 14 | 15 | public async Task SaveChanges() 16 | { 17 | await _context.SaveChangesAsync(); 18 | } 19 | 20 | public async Task> GetAllCommands() 21 | { 22 | return await _context.Commands!.ToListAsync(); 23 | } 24 | 25 | public async Task CreateCommand(Command cmd) 26 | { 27 | if (cmd == null) 28 | { 29 | throw new ArgumentNullException(nameof(cmd)); 30 | } 31 | 32 | await _context.Commands!.AddAsync(cmd); 33 | } 34 | 35 | public async Task GetCommandById(int id) 36 | { 37 | return await _context.Commands!.FirstOrDefaultAsync(c => c.Id == id); 38 | } 39 | 40 | 41 | 42 | public void DeleteCommand(Command cmd) 43 | { 44 | if (cmd == null) 45 | { 46 | throw new ArgumentNullException(nameof(cmd)); 47 | } 48 | _context.Commands.Remove(cmd); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /SixAPI/Data/ICommandRepo.cs: -------------------------------------------------------------------------------- 1 | using SixAPI.Models; 2 | 3 | namespace SixAPI.Data 4 | { 5 | public interface ICommandRepo 6 | { 7 | Task SaveChanges(); 8 | 9 | Task> GetAllCommands(); 10 | Task GetCommandById(int id); 11 | Task CreateCommand(Command cmd); 12 | 13 | void DeleteCommand(Command cmd); 14 | } 15 | } -------------------------------------------------------------------------------- /SixAPI/Dtos/CommandCreateDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixAPI.Dtos 4 | { 5 | public class CommandCreateDto 6 | { 7 | [Required] 8 | public string? HowTo { get; set; } 9 | 10 | [Required] 11 | [MaxLength(7)] 12 | public string? Platform { get; set; } 13 | 14 | [Required] 15 | public string? CommandLine { get; set; } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /SixAPI/Dtos/CommandReadDto.cs: -------------------------------------------------------------------------------- 1 | namespace SixAPI.Dtos 2 | { 3 | public class CommandReadDto 4 | { 5 | 6 | public int Id { get; set; } 7 | 8 | 9 | public string? HowTo { get; set; } 10 | 11 | 12 | public string? Platform { get; set; } 13 | 14 | 15 | public string? CommandLine { get; set; } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /SixAPI/Dtos/CommandUpdateDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixAPI.Dtos 4 | { 5 | public class CommandUpdateDto 6 | { 7 | [Required] 8 | public string? HowTo { get; set; } 9 | 10 | [Required] 11 | [MaxLength(8)] 12 | public string? Platform { get; set; } 13 | 14 | [Required] 15 | public string? CommandLine { get; set; } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /SixAPI/Dtos/PlatformCreateDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixAPI.Dtos 4 | { 5 | public class PlatformCreateDto 6 | { 7 | [Required] 8 | public string? PlatformName { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /SixAPI/Migrations/20220428004042_InitialMigration.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using SixAPI.Data; 8 | 9 | #nullable disable 10 | 11 | namespace SixAPI.Migrations 12 | { 13 | [DbContext(typeof(AppDbContext))] 14 | [Migration("20220428004042_InitialMigration")] 15 | partial class InitialMigration 16 | { 17 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 18 | { 19 | #pragma warning disable 612, 618 20 | modelBuilder 21 | .HasAnnotation("ProductVersion", "6.0.4") 22 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 23 | 24 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 25 | 26 | modelBuilder.Entity("SixAPi.Models.Command", b => 27 | { 28 | b.Property("Id") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("int"); 31 | 32 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 33 | 34 | b.Property("CommandLine") 35 | .IsRequired() 36 | .HasColumnType("nvarchar(max)"); 37 | 38 | b.Property("HowTo") 39 | .IsRequired() 40 | .HasColumnType("nvarchar(max)"); 41 | 42 | b.Property("Platform") 43 | .IsRequired() 44 | .HasColumnType("nvarchar(max)"); 45 | 46 | b.HasKey("Id"); 47 | 48 | b.ToTable("Commands"); 49 | }); 50 | #pragma warning restore 612, 618 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SixAPI/Migrations/20220428004042_InitialMigration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace SixAPI.Migrations 6 | { 7 | public partial class InitialMigration : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Commands", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("SqlServer:Identity", "1, 1"), 17 | HowTo = table.Column(type: "nvarchar(max)", nullable: false), 18 | Platform = table.Column(type: "nvarchar(max)", nullable: false), 19 | CommandLine = table.Column(type: "nvarchar(max)", nullable: false) 20 | }, 21 | constraints: table => 22 | { 23 | table.PrimaryKey("PK_Commands", x => x.Id); 24 | }); 25 | } 26 | 27 | protected override void Down(MigrationBuilder migrationBuilder) 28 | { 29 | migrationBuilder.DropTable( 30 | name: "Commands"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SixAPI/Migrations/20220518060742_add-platforms.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using SixAPI.Data; 8 | 9 | #nullable disable 10 | 11 | namespace SixAPI.Migrations 12 | { 13 | [DbContext(typeof(AppDbContext))] 14 | [Migration("20220518060742_add-platforms")] 15 | partial class addplatforms 16 | { 17 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 18 | { 19 | #pragma warning disable 612, 618 20 | modelBuilder 21 | .HasAnnotation("ProductVersion", "6.0.4") 22 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 23 | 24 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 25 | 26 | modelBuilder.Entity("SixAPi.Models.Command", b => 27 | { 28 | b.Property("Id") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("int"); 31 | 32 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 33 | 34 | b.Property("CommandLine") 35 | .IsRequired() 36 | .HasColumnType("nvarchar(max)"); 37 | 38 | b.Property("HowTo") 39 | .IsRequired() 40 | .HasColumnType("nvarchar(max)"); 41 | 42 | b.Property("Platform") 43 | .IsRequired() 44 | .HasMaxLength(5) 45 | .HasColumnType("nvarchar(5)"); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.ToTable("Commands"); 50 | }); 51 | 52 | modelBuilder.Entity("SixAPI.Models.Platform", b => 53 | { 54 | b.Property("Id") 55 | .ValueGeneratedOnAdd() 56 | .HasColumnType("int"); 57 | 58 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 59 | 60 | b.Property("PlatformName") 61 | .IsRequired() 62 | .HasColumnType("nvarchar(max)"); 63 | 64 | b.HasKey("Id"); 65 | 66 | b.ToTable("Platforms"); 67 | }); 68 | #pragma warning restore 612, 618 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SixAPI/Migrations/20220518060742_add-platforms.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace SixAPI.Migrations 6 | { 7 | public partial class addplatforms : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.AlterColumn( 12 | name: "Platform", 13 | table: "Commands", 14 | type: "nvarchar(5)", 15 | maxLength: 5, 16 | nullable: false, 17 | oldClrType: typeof(string), 18 | oldType: "nvarchar(max)"); 19 | 20 | migrationBuilder.CreateTable( 21 | name: "Platforms", 22 | columns: table => new 23 | { 24 | Id = table.Column(type: "int", nullable: false) 25 | .Annotation("SqlServer:Identity", "1, 1"), 26 | PlatformName = table.Column(type: "nvarchar(max)", nullable: false) 27 | }, 28 | constraints: table => 29 | { 30 | table.PrimaryKey("PK_Platforms", x => x.Id); 31 | }); 32 | } 33 | 34 | protected override void Down(MigrationBuilder migrationBuilder) 35 | { 36 | migrationBuilder.DropTable( 37 | name: "Platforms"); 38 | 39 | migrationBuilder.AlterColumn( 40 | name: "Platform", 41 | table: "Commands", 42 | type: "nvarchar(max)", 43 | nullable: false, 44 | oldClrType: typeof(string), 45 | oldType: "nvarchar(5)", 46 | oldMaxLength: 5); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SixAPI/Migrations/AppDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using SixAPI.Data; 7 | 8 | #nullable disable 9 | 10 | namespace SixAPI.Migrations 11 | { 12 | [DbContext(typeof(AppDbContext))] 13 | partial class AppDbContextModelSnapshot : ModelSnapshot 14 | { 15 | protected override void BuildModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "6.0.4") 20 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 21 | 22 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 23 | 24 | modelBuilder.Entity("SixAPi.Models.Command", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("int"); 29 | 30 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 31 | 32 | b.Property("CommandLine") 33 | .IsRequired() 34 | .HasColumnType("nvarchar(max)"); 35 | 36 | b.Property("HowTo") 37 | .IsRequired() 38 | .HasColumnType("nvarchar(max)"); 39 | 40 | b.Property("Platform") 41 | .IsRequired() 42 | .HasMaxLength(5) 43 | .HasColumnType("nvarchar(5)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.ToTable("Commands"); 48 | }); 49 | 50 | modelBuilder.Entity("SixAPI.Models.Platform", b => 51 | { 52 | b.Property("Id") 53 | .ValueGeneratedOnAdd() 54 | .HasColumnType("int"); 55 | 56 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 57 | 58 | b.Property("PlatformName") 59 | .IsRequired() 60 | .HasColumnType("nvarchar(max)"); 61 | 62 | b.HasKey("Id"); 63 | 64 | b.ToTable("Platforms"); 65 | }); 66 | #pragma warning restore 612, 618 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SixAPI/Models/Command.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace SixAPI.Models 5 | { 6 | public class Command 7 | { 8 | [Key] 9 | public int Id { get; set; } 10 | 11 | [Required] 12 | public string? HowTo { get; set; } 13 | 14 | [Required] 15 | [MaxLength(5)] 16 | public string? Platform { get; set; } 17 | 18 | [Required] 19 | public string? CommandLine { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /SixAPI/Models/Platform.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SixAPI.Binders; 4 | 5 | namespace SixAPI.Models 6 | { 7 | 8 | [ModelBinder(BinderType = typeof(PlatformModelBinder))] 9 | public class Platform 10 | { 11 | [Key] 12 | public int Id { get; set; } 13 | 14 | [Required] 15 | public string? PlatformName { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /SixAPI/Profiles/CommandsProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SixAPI.Dtos; 3 | using SixAPI.Models; 4 | 5 | namespace SixAPI.Profiles 6 | { 7 | public class CommandsProfile : Profile 8 | { 9 | public CommandsProfile() 10 | { 11 | // Source -> Target 12 | CreateMap(); 13 | CreateMap(); 14 | CreateMap(); 15 | CreateMap(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /SixAPI/Profiles/PlatformsProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SixAPI.Dtos; 3 | using SixAPI.Models; 4 | 5 | namespace SixAPI.Profiles 6 | { 7 | public class PlatformsProfile : Profile 8 | { 9 | public PlatformsProfile() 10 | { 11 | // Source -> Target 12 | 13 | CreateMap(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /SixAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Data.SqlClient; 2 | using Microsoft.EntityFrameworkCore; 3 | using SixAPI.Data; 4 | using SixAPI.Controllers; 5 | using Newtonsoft.Json.Serialization; 6 | 7 | var builder = WebApplication.CreateBuilder(args); 8 | 9 | 10 | builder.Services.AddControllers().AddNewtonsoftJson(s => { 11 | s.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 12 | }); 13 | 14 | 15 | builder.Services.AddEndpointsApiExplorer(); 16 | builder.Services.AddSwaggerGen(); 17 | 18 | var sqlConBuilder = new SqlConnectionStringBuilder(); 19 | 20 | sqlConBuilder.ConnectionString = builder.Configuration.GetConnectionString("SQLDbConnection"); 21 | sqlConBuilder.UserID = builder.Configuration["UserId"]; 22 | sqlConBuilder.Password = builder.Configuration["Password"]; 23 | 24 | builder.Services.AddDbContext(opt => opt.UseSqlServer(sqlConBuilder.ConnectionString)); 25 | builder.Services.AddScoped(); 26 | builder.Services.AddScoped(); 27 | builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); 28 | 29 | var app = builder.Build(); 30 | 31 | 32 | if (app.Environment.IsDevelopment()) 33 | { 34 | app.UseSwagger(); 35 | app.UseSwaggerUI(); 36 | } 37 | 38 | app.UseHttpsRedirection(); 39 | 40 | app.UseAuthorization(); 41 | 42 | app.MapControllers(); 43 | 44 | app.Run(); 45 | -------------------------------------------------------------------------------- /SixAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:24133", 8 | "sslPort": 44384 9 | } 10 | }, 11 | "profiles": { 12 | "SixAPI": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "https://localhost:7014;http://localhost:5072", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "launchUrl": "swagger", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SixAPI/SixAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | S05E03-max-1a0f9154-9e20-40dc-b9d2-669ac961a04d 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /SixAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": 9 | { 10 | "SQLDbConnection" : "Server=localhost,1433;Initial Catalog=CommanderDB" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SixAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /SixAPI/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | sqlserver: 4 | image: "mcr.microsoft.com/mssql/server:2019-latest" 5 | environment: 6 | ACCEPT_EULA: "Y" 7 | SA_PASSWORD: "pa55w0rd!" 8 | MSSQL_PID: "Express" 9 | ports: 10 | - "1433:1433" -------------------------------------------------------------------------------- /SixMinApi/Data/AppDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using SixMinApi.Models; 3 | 4 | namespace SixMinApi.Data 5 | { 6 | public class AppDbContext : DbContext 7 | { 8 | public AppDbContext(DbContextOptions options) : base(options) 9 | { 10 | 11 | } 12 | 13 | public DbSet Commands => Set(); 14 | } 15 | } -------------------------------------------------------------------------------- /SixMinApi/Data/CommandRepo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using SixMinApi.Models; 3 | 4 | namespace SixMinApi.Data 5 | { 6 | public class CommandRepo : ICommandRepo 7 | { 8 | private readonly AppDbContext _context; 9 | 10 | public CommandRepo(AppDbContext context) 11 | { 12 | _context = context; 13 | } 14 | 15 | public async Task CreateCommand(Command cmd) 16 | { 17 | if(cmd == null) 18 | { 19 | throw new ArgumentNullException(nameof(cmd)); 20 | } 21 | 22 | await _context.AddAsync(cmd); 23 | } 24 | 25 | public void DeleteCommand(Command cmd) 26 | { 27 | if(cmd == null) 28 | { 29 | throw new ArgumentNullException(nameof(cmd)); 30 | } 31 | 32 | _context.Commands.Remove(cmd); 33 | } 34 | 35 | public async Task> GetAllCommands() 36 | { 37 | return await _context.Commands.ToListAsync(); 38 | } 39 | 40 | public async Task GetCommandById(int id) 41 | { 42 | return await _context.Commands.FirstOrDefaultAsync(c => c.Id == id); 43 | } 44 | 45 | public async Task SaveChanges() 46 | { 47 | await _context.SaveChangesAsync(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /SixMinApi/Data/ICommandRepo.cs: -------------------------------------------------------------------------------- 1 | using SixMinApi.Models; 2 | 3 | namespace SixMinApi.Data 4 | { 5 | public interface ICommandRepo 6 | { 7 | Task SaveChanges(); 8 | Task GetCommandById(int id); 9 | Task> GetAllCommands(); 10 | Task CreateCommand(Command cmd); 11 | 12 | void DeleteCommand(Command cmd); 13 | } 14 | } -------------------------------------------------------------------------------- /SixMinApi/Dtos/CommandCreateDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixMinApi.Dtos 4 | { 5 | public class CommandCreateDto 6 | { 7 | [Required] 8 | public string? HowTo { get; set; } 9 | 10 | [Required] 11 | [MaxLength(5)] 12 | public string? Platform { get; set; } 13 | 14 | [Required] 15 | public string? CommandLine { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /SixMinApi/Dtos/CommandReadDto.cs: -------------------------------------------------------------------------------- 1 | namespace SixMinApi.Dtos 2 | { 3 | public class CommandReadDto 4 | { 5 | public int Id { get; set; } 6 | 7 | public string? HowTo { get; set; } 8 | 9 | public string? Platform { get; set; } 10 | 11 | public string? CommandLine { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /SixMinApi/Dtos/CommandUpdateDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixMinApi.Dtos 4 | { 5 | public class CommandUpdateDto 6 | { 7 | [Required] 8 | public string? HowTo { get; set; } 9 | 10 | [Required] 11 | [MaxLength(5)] 12 | public string? Platform { get; set; } 13 | 14 | [Required] 15 | public string? CommandLine { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /SixMinApi/Migrations/20220522055326_initialmigration.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using SixMinApi.Data; 8 | 9 | #nullable disable 10 | 11 | namespace SixMinApi.Migrations 12 | { 13 | [DbContext(typeof(AppDbContext))] 14 | [Migration("20220522055326_initialmigration")] 15 | partial class initialmigration 16 | { 17 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 18 | { 19 | #pragma warning disable 612, 618 20 | modelBuilder 21 | .HasAnnotation("ProductVersion", "6.0.5") 22 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 23 | 24 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 25 | 26 | modelBuilder.Entity("SixMinApi.Models.Command", b => 27 | { 28 | b.Property("Id") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("int"); 31 | 32 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 33 | 34 | b.Property("CommandLine") 35 | .IsRequired() 36 | .HasColumnType("nvarchar(max)"); 37 | 38 | b.Property("HowTo") 39 | .IsRequired() 40 | .HasColumnType("nvarchar(max)"); 41 | 42 | b.Property("Platform") 43 | .IsRequired() 44 | .HasMaxLength(5) 45 | .HasColumnType("nvarchar(5)"); 46 | 47 | b.HasKey("Id"); 48 | 49 | b.ToTable("Commands"); 50 | }); 51 | #pragma warning restore 612, 618 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SixMinApi/Migrations/20220522055326_initialmigration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace SixMinApi.Migrations 6 | { 7 | public partial class initialmigration : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Commands", 13 | columns: table => new 14 | { 15 | Id = table.Column(type: "int", nullable: false) 16 | .Annotation("SqlServer:Identity", "1, 1"), 17 | HowTo = table.Column(type: "nvarchar(max)", nullable: false), 18 | Platform = table.Column(type: "nvarchar(5)", maxLength: 5, nullable: false), 19 | CommandLine = table.Column(type: "nvarchar(max)", nullable: false) 20 | }, 21 | constraints: table => 22 | { 23 | table.PrimaryKey("PK_Commands", x => x.Id); 24 | }); 25 | } 26 | 27 | protected override void Down(MigrationBuilder migrationBuilder) 28 | { 29 | migrationBuilder.DropTable( 30 | name: "Commands"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SixMinApi/Migrations/AppDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Infrastructure; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using SixMinApi.Data; 7 | 8 | #nullable disable 9 | 10 | namespace SixMinApi.Migrations 11 | { 12 | [DbContext(typeof(AppDbContext))] 13 | partial class AppDbContextModelSnapshot : ModelSnapshot 14 | { 15 | protected override void BuildModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "6.0.5") 20 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 21 | 22 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 23 | 24 | modelBuilder.Entity("SixMinApi.Models.Command", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("int"); 29 | 30 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 31 | 32 | b.Property("CommandLine") 33 | .IsRequired() 34 | .HasColumnType("nvarchar(max)"); 35 | 36 | b.Property("HowTo") 37 | .IsRequired() 38 | .HasColumnType("nvarchar(max)"); 39 | 40 | b.Property("Platform") 41 | .IsRequired() 42 | .HasMaxLength(5) 43 | .HasColumnType("nvarchar(5)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.ToTable("Commands", (string)null); 48 | }); 49 | #pragma warning restore 612, 618 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SixMinApi/Models/Command.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SixMinApi.Models 4 | { 5 | public class Command 6 | { 7 | [Key] 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | public string? HowTo { get; set; } 12 | 13 | [Required] 14 | [MaxLength(6)] 15 | public string? Platform { get; set; } 16 | 17 | [Required] 18 | public string? CommandLine { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /SixMinApi/Profiles/CommandsProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SixMinApi.Dtos; 3 | using SixMinApi.Models; 4 | 5 | namespace SixMinApi.Profiles 6 | { 7 | public class CommandsProfile : Profile 8 | { 9 | public CommandsProfile() 10 | { 11 | // Source -> Target 12 | CreateMap(); 13 | CreateMap(); 14 | CreateMap(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /SixMinApi/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | using AutoMapper; 3 | using Microsoft.Data.SqlClient; 4 | using Microsoft.EntityFrameworkCore; 5 | using SixMinApi.Data; 6 | using SixMinApi.Dtos; 7 | using SixMinApi.Models; 8 | 9 | var builder = WebApplication.CreateBuilder(args); 10 | 11 | builder.Services.AddEndpointsApiExplorer(); 12 | builder.Services.AddSwaggerGen(); 13 | 14 | var sqlConBuilder = new SqlConnectionStringBuilder(); 15 | 16 | sqlConBuilder.ConnectionString = builder.Configuration.GetConnectionString("SQLDbConnection"); 17 | sqlConBuilder.UserID = builder.Configuration["UserID"]; 18 | sqlConBuilder.Password = builder.Configuration["Password"]; 19 | 20 | builder.Services.AddDbContext(opt => opt.UseSqlServer(sqlConBuilder.ConnectionString)); 21 | builder.Services.AddScoped(); 22 | builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); 23 | 24 | var app = builder.Build(); 25 | 26 | 27 | if (app.Environment.IsDevelopment()) 28 | { 29 | app.UseSwagger(); 30 | app.UseSwaggerUI(); 31 | } 32 | 33 | app.UseHttpsRedirection(); 34 | 35 | app.MapGet("api/v1/commands", async (ICommandRepo repo, IMapper mapper) => { 36 | var commands = await repo.GetAllCommands(); 37 | return Results.Ok(mapper.Map>(commands)); 38 | }); 39 | 40 | app.MapGet("api/v1/commands/{id}", async (ICommandRepo repo, IMapper mapper, int id) => { 41 | var command = await repo.GetCommandById(id); 42 | if (command != null) 43 | { 44 | return Results.Ok(mapper.Map(command)); 45 | } 46 | return Results.NotFound(); 47 | }); 48 | 49 | app.MapPost("api/v1/commands", async (ICommandRepo repo, IMapper mapper, CommandCreateDto cmdCreateDto) => { 50 | var commandModel = mapper.Map(cmdCreateDto); 51 | 52 | await repo.CreateCommand(commandModel); 53 | await repo.SaveChanges(); 54 | 55 | var cmdReadDto = mapper.Map(commandModel); 56 | 57 | return Results.Created($"api/v1/commands/{cmdReadDto.Id}", cmdReadDto); 58 | 59 | }); 60 | 61 | app.MapPut("api/v1/commands/{id}", async (ICommandRepo repo, IMapper mapper, int id, CommandUpdateDto cmdUpdateDto) => { 62 | var command = await repo.GetCommandById(id); 63 | if (command == null) 64 | { 65 | return Results.NotFound(); 66 | } 67 | 68 | mapper.Map(cmdUpdateDto, command); 69 | 70 | await repo.SaveChanges(); 71 | 72 | return Results.NoContent(); 73 | }); 74 | 75 | app.MapDelete("api/v1/commands/{id}", async (ICommandRepo repo, IMapper mapper, int id) => { 76 | var command = await repo.GetCommandById(id); 77 | if (command == null) 78 | { 79 | return Results.NotFound(); 80 | } 81 | 82 | repo.DeleteCommand(command); 83 | 84 | await repo.SaveChanges(); 85 | 86 | return Results.NoContent(); 87 | 88 | }); 89 | 90 | app.Run(); 91 | 92 | -------------------------------------------------------------------------------- /SixMinApi/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:36242", 8 | "sslPort": 44307 9 | } 10 | }, 11 | "profiles": { 12 | "SixMinApi": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "https://localhost:7126;http://localhost:5072", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "launchUrl": "swagger", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SixMinApi/SixMinApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 21e2fca2-e699-41cb-ba09-63d84aa27ccd 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SixMinApi/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": 9 | { 10 | "SQLDbConnection" : "Server=localhost,1433;Initial Catalog=CommandDb" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SixMinApi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /SixMinApi/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | sqlserver: 4 | image: "mcr.microsoft.com/mssql/server:2019-latest" 5 | environment: 6 | ACCEPT_EULA: "Y" 7 | SA_PASSWORD: "pa55w0rd!" 8 | MSSQL_PID: "Express" 9 | ports: 10 | - "1433:1433" --------------------------------------------------------------------------------