From a19c50c0c5c516af2e82f13b8bb6c1930341799f Mon Sep 17 00:00:00 2001 From: adamjstone <8525409+adamjstone@users.noreply.github.com> Date: Tue, 29 Sep 2020 10:51:32 -0500 Subject: [PATCH] #371 Add HTTP API example application. --- RapidField.SolidInstruments.sln | 7 ++ cicd/modules/AutomationTools.psm1 | 66 +++++++++++++++++++ en-US_User.dic | 1 + .../ApplicationDependencyPackage.cs | 6 +- .../Controllers/UserController.cs | 31 +++++++-- .../Program.cs | 12 +++- .../README.md | 30 +++++++++ ...idInstruments.Example.HttpApiClient.csproj | 33 ++++++++++ 8 files changed, 176 insertions(+), 10 deletions(-) create mode 100644 example/RapidField.SolidInstruments.Example.HttpApiClient/README.md create mode 100644 example/RapidField.SolidInstruments.Example.HttpApiClient/RapidField.SolidInstruments.Example.HttpApiClient.csproj diff --git a/RapidField.SolidInstruments.sln b/RapidField.SolidInstruments.sln index 1db19f90..d2f1497c 100644 --- a/RapidField.SolidInstruments.sln +++ b/RapidField.SolidInstruments.sln @@ -424,6 +424,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments.Web.DotNetNative", "src\RapidField.SolidInstruments.Web.DotNetNative\RapidField.SolidInstruments.Web.DotNetNative.csproj", "{6A53C072-71C8-42F1-90D9-9AE64F2848B2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments.Example.HttpApiClient", "example\RapidField.SolidInstruments.Example.HttpApiClient\RapidField.SolidInstruments.Example.HttpApiClient.csproj", "{46A9050C-F99A-4F93-B98B-B67A53A3FA0A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -674,6 +676,10 @@ Global {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Release|Any CPU.Build.0 = Release|Any CPU + {46A9050C-F99A-4F93-B98B-B67A53A3FA0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46A9050C-F99A-4F93-B98B-B67A53A3FA0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46A9050C-F99A-4F93-B98B-B67A53A3FA0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46A9050C-F99A-4F93-B98B-B67A53A3FA0A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -756,6 +762,7 @@ Global {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7} {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7} {6A53C072-71C8-42F1-90D9-9AE64F2848B2} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7} + {46A9050C-F99A-4F93-B98B-B67A53A3FA0A} = {BEB60D41-11BB-4C6E-8F5D-1E7990A27C34} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {834FCFB0-DA00-4ABD-9424-6FE1398A9F6E} diff --git a/cicd/modules/AutomationTools.psm1 b/cicd/modules/AutomationTools.psm1 index 0363edae..0fa46bac 100644 --- a/cicd/modules/AutomationTools.psm1 +++ b/cicd/modules/AutomationTools.psm1 @@ -40,6 +40,7 @@ $ChoclateyPackageNameForDotNetCoreSdk = "dotnetcore-sdk"; $ChoclateyPackageNameForHub = "hub"; $ChoclateyPackageNameForLeanify = "leanify"; $ChoclateyPackageNameForNodeJs = "nodejs"; +$ChoclateyPackageNameForNSwagStudio = "nswagstudio"; $ChoclateyPackageNameForOpenCover = "opencover.portable"; $ChoclateyPackageNameForOpenSsl = "openssl.light"; $ChoclateyPackageNameForPsake = "psake"; @@ -71,6 +72,7 @@ $SuppressHtmlMinifier = $false; $SuppressHub = $true; $SuppressLeanify = $true; $SuppressNodeJs = $false; +$SuppressNSwagStudio = $false; $SuppressNuGet = $false; $SuppressOpenCover = $false; $SuppressOpenSsl = $true; @@ -155,6 +157,15 @@ Function GetNodeJsInstallationStatus Return (GetChocolateyInstallationStatus) -and (choco list -lo | Where-Object { $_.ToLower().StartsWith("$ChoclateyPackageNameForNodeJs") }); } +<# +.Synopsis +Returns a boolean value indicating whether or not NSwagStudio is installed in the current environment. +#> +Function GetNSwagStudioInstallationStatus +{ + Return (GetChocolateyInstallationStatus) -and (choco list -lo | Where-Object { $_.ToLower().StartsWith("$ChoclateyPackageNameForNSwagStudio") }); +} + <# .Synopsis Returns a boolean value indicating whether or not NuGet is installed in the current environment. @@ -232,6 +243,7 @@ Function InstallAllAutomationTools InstallHtmlMinifier; InstallHub; InstallLeanify; + InstallNSwagStudio; InstallOpenCover; InstallOpenSsl; InstallPoshGit; @@ -424,6 +436,28 @@ Function InstallNodeJs ComposeFinish "Finished installing Node.js."; } +<# +.Synopsis +Installs NSwagStudio in the current environment. +#> +Function InstallNSwagStudio +{ + If ($SuppressNSwagStudio -eq $true) + { + ComposeNormal "Suppressing installation of NSwagStudio."; + Return; + } + ElseIf (GetNSwagStudioInstallationStatus) + { + ComposeNormal "NSwagStudio is already installed."; + Return; + } + + ComposeStart "Installing NSwagStudio."; + UseChocolateyToInstall -PackageName "$ChoclateyPackageNameForNSwagStudio"; + ComposeFinish "Finished installing NSwagStudio."; +} + <# .Synopsis Installs NuGet in the current environment. @@ -806,6 +840,18 @@ Function RestoreNodeJs ComposeFinish "Finished restoring Node.js."; } +<# +.Synopsis +Uninstalls, if necessary, and installs NSwagStudio in the current environment. +#> +Function RestoreNSwagStudio +{ + ComposeStart "Restoring NSwagStudio."; + UninstallNSwagStudio; + InstallNSwagStudio; + ComposeFinish "Finished restoring NSwagStudio."; +} + <# .Synopsis Uninstalls, if necessary, and installs NuGet in the current environment. @@ -903,6 +949,7 @@ Function UninstallAllAutomationTools UninstallHtmlMinifier; UninstallHub; UninstallLeanify; + UninstallNSwagStudio; UninstallOpenCover; UninstallOpenSsl; UninstallPoshGit; @@ -1045,6 +1092,25 @@ Function UninstallNodeJs } } +<# +.Synopsis +Uninstalls NSwagStudio in the current environment. +#> +Function UninstallNSwagStudio +{ + If ($SuppressNSwagStudio -eq $true) + { + ComposeNormal "Suppressing uninstallation of NSwagStudio."; + Return; + } + ElseIf (GetNSwagStudioInstallationStatus) + { + ComposeStart "Uninstalling NSwagStudio."; + UseChocolateyToUninstall -PackageName "$ChoclateyPackageNameForNSwagStudio"; + ComposeFinish "Finished uninstalling NSwagStudio."; + } +} + <# .Synopsis Uninstalls NuGet in the current environment. diff --git a/en-US_User.dic b/en-US_User.dic index 87c905a9..8ee46e27 100644 --- a/en-US_User.dic +++ b/en-US_User.dic @@ -179,6 +179,7 @@ noindex nologo norepair npm +nswagstudio nuget nullable Nwn diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs index 1a8202e0..769e40d9 100644 --- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs +++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs @@ -35,10 +35,12 @@ public ApplicationDependencyPackage() /// protected override IEnumerable> CreateModules(IConfiguration applicationConfiguration) => new IDependencyModule[] { - new ApplicationDependencyModule(applicationConfiguration), new DatabaseContextDependencyModule(applicationConfiguration), new ServiceBusDependencyModule(applicationConfiguration), - new MessageHandlerModule(applicationConfiguration) + new CommandHandlerModule(applicationConfiguration), + new EventHandlerModule(applicationConfiguration), + new MessageHandlerModule(applicationConfiguration), + new ApplicationDependencyModule(applicationConfiguration) }; } } \ No newline at end of file diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs index ed09cf8b..847f1204 100644 --- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs +++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs @@ -2,15 +2,18 @@ // Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. // ================================================================================================================================= +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using RapidField.SolidInstruments.Command; using RapidField.SolidInstruments.Core.ArgumentValidation; using RapidField.SolidInstruments.Example.Domain.Commands.ModelState.User; using RapidField.SolidInstruments.Example.Domain.Messages.Command.ModelState.User; using RapidField.SolidInstruments.Example.Domain.Models.User; +using RapidField.SolidInstruments.Serialization; using System; using System.Diagnostics; using System.Net; +using System.Text; namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.Controllers { @@ -46,7 +49,12 @@ public UserController(ICommandMediator mediator) /// A status code result. /// [HttpDelete] - public IActionResult Delete([FromRoute] Guid identifier) + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Route("{identifier:Guid}")] + public ActionResult Delete([FromRoute] Guid identifier) { try { @@ -81,7 +89,12 @@ public IActionResult Delete([FromRoute] Guid identifier) /// model exists. /// [HttpGet] - public IActionResult Get([FromQuery] Guid identifier) + [ProducesResponseType(typeof(DomainModel), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Route("{identifier:Guid}")] + public ActionResult Get([FromRoute] Guid identifier) { try { @@ -92,7 +105,9 @@ public IActionResult Get([FromQuery] Guid identifier) return NotFound(identifier); } - return new JsonResult(model); + var serializer = new JsonSerializer(); + var response = Encoding.UTF8.GetString(serializer.Serialize(model)); + return Ok(response); } catch (ArgumentException exception) { @@ -114,7 +129,10 @@ public IActionResult Get([FromQuery] Guid identifier) /// A status code result. /// [HttpPost] - public IActionResult Post([FromBody] DomainModel model) + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public ActionResult Post([FromBody] DomainModel model) { try { @@ -141,7 +159,10 @@ public IActionResult Post([FromBody] DomainModel model) /// A status code result. /// [HttpPut] - public IActionResult Put([FromBody] DomainModel model) + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public ActionResult Put([FromBody] DomainModel model) { try { diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs index 50427d0f..e5a3ee75 100644 --- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs +++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs @@ -4,10 +4,13 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using RapidField.SolidInstruments.InversionOfControl.DotNetNative.Extensions; using System; using System.Diagnostics; +using System.IO; namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi { @@ -24,14 +27,17 @@ public static class Program /// public static void Main(String[] args) { - //using var webExecutor = new ApplicationWebExecutor(ApplicationName); - //webExecutor.Execute(args); + var applicationConfiguration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .Build(); var host = Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webHost => { + webHost.UseConfiguration(applicationConfiguration); webHost.ConfigureServices(services => { - services.AddControllers(); + services.AddDependencyPackage(new ApplicationDependencyPackage(), applicationConfiguration); }); webHost.Configure(application => { diff --git a/example/RapidField.SolidInstruments.Example.HttpApiClient/README.md b/example/RapidField.SolidInstruments.Example.HttpApiClient/README.md new file mode 100644 index 00000000..8cfef86c --- /dev/null +++ b/example/RapidField.SolidInstruments.Example.HttpApiClient/README.md @@ -0,0 +1,30 @@ + + +[![Solid Instruments](../../SolidInstruments.Logo.Color.Transparent.500w.png)](../../README.md) +- - - + +# RapidField.SolidInstruments.Example.HttpApiClient + +This document describes the purpose of the [`RapidField.SolidInstruments.Example.HttpApiClient`]() project. + +## Purpose + +This project exposes a sample collection of HTTP API clients that utilize the **Solid Instruments** [web](../../src/RapidField.SolidInstruments.Web/README.md) constructs. + +## License + +[![License](https://img.shields.io/github/license/rapidfield/solid-instruments?style=flat&color=lightseagreen&label=license&logo=open-access&logoColor=lightgrey)](../../LICENSE.txt) + +**Solid Instruments** is [MIT-licensed](https://en.wikipedia.org/wiki/MIT_License). Review the [license terms](../../LICENSE.txt) for more information. + +
+ +- - - + +
+ +[![RapidField](../../RapidField.Logo.Color.Black.Transparent.200w.png)](https://www.rapidfield.com) + +###### Copyright (c) RapidField LLC. All rights reserved. "RapidField" and "Solid Instruments" are trademarks of RapidField LLC. \ No newline at end of file diff --git a/example/RapidField.SolidInstruments.Example.HttpApiClient/RapidField.SolidInstruments.Example.HttpApiClient.csproj b/example/RapidField.SolidInstruments.Example.HttpApiClient/RapidField.SolidInstruments.Example.HttpApiClient.csproj new file mode 100644 index 00000000..f3358228 --- /dev/null +++ b/example/RapidField.SolidInstruments.Example.HttpApiClient/RapidField.SolidInstruments.Example.HttpApiClient.csproj @@ -0,0 +1,33 @@ + + + + + Solid Instruments contributors + RapidField + Copyright (c) RapidField LLC. All rights reserved. + Solid Instruments + This project exposes a sample collection of HTTP API clients that utilize the Solid Instruments web constructs. + $(BuildVersion) + netstandard2.1 + latest + + + bin\Debug\netstandard2.1\RapidField.SolidInstruments.Example.HttpApiClient.xml + true + + + + bin\Release\netstandard2.1\RapidField.SolidInstruments.Example.HttpApiClient.xml + true + + + + + + + + + + \ No newline at end of file