diff --git a/src/LittleBlocks.sln b/src/LittleBlocks.sln
index 3c9d8ba..94e751b 100644
--- a/src/LittleBlocks.sln
+++ b/src/LittleBlocks.sln
@@ -82,6 +82,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extras", "Extras", "{B2C58A
..\GitVersion.yml = ..\GitVersion.yml
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LittleBlocks.Sample.Minimal.WebAPI", "Samples\LittleBlocks.Sample.MinimalApi..WebAPI\LittleBlocks.Sample.Minimal.WebAPI.csproj", "{22C0106F-3EFC-46E4-863C-4861F794F917}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -216,6 +218,10 @@ Global
{0A9E6275-2F18-43DC-86DC-C3F3F37FB177}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A9E6275-2F18-43DC-86DC-C3F3F37FB177}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A9E6275-2F18-43DC-86DC-C3F3F37FB177}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22C0106F-3EFC-46E4-863C-4861F794F917}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22C0106F-3EFC-46E4-863C-4861F794F917}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22C0106F-3EFC-46E4-863C-4861F794F917}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22C0106F-3EFC-46E4-863C-4861F794F917}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -255,6 +261,7 @@ Global
{74F7FFB2-57CB-4217-976A-B0916B20AD05} = {C6B49B11-8BC9-4A68-9238-85BECC4BDF97}
{15A17D77-C9BE-4ADE-A42A-0DB5C88D4A0C} = {C6B49B11-8BC9-4A68-9238-85BECC4BDF97}
{0A9E6275-2F18-43DC-86DC-C3F3F37FB177} = {709EFF89-FE7B-4818-B435-856741E1C21B}
+ {22C0106F-3EFC-46E4-863C-4861F794F917} = {709EFF89-FE7B-4818-B435-856741E1C21B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AD317B39-D1E3-4033-A80A-C5F8CACAAF2C}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AuthenticationController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AuthenticationController.cs
new file mode 100644
index 0000000..e6904ce
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AuthenticationController.cs
@@ -0,0 +1,41 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class AuthenticationController : Controller
+{
+ public AuthenticationController(ILogger logger)
+ {
+ Log = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ private ILogger Log { get; }
+
+ [HttpGet("secured")]
+ [Authorize]
+ public IActionResult GetSecured()
+ {
+ return Ok();
+ }
+
+ [HttpGet("unsecured")]
+ public IActionResult GetUnsecured()
+ {
+ return Ok();
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AutomapperController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AutomapperController.cs
new file mode 100644
index 0000000..6846dd2
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/AutomapperController.cs
@@ -0,0 +1,56 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class AutomapperController : Controller
+{
+ private readonly ITypeMapper _mapper;
+
+ public AutomapperController(ITypeMapper mapper)
+ {
+ if (mapper == null) throw new ArgumentNullException(nameof(mapper));
+ _mapper = mapper;
+ }
+
+ [HttpGet("person/{firstname}/{lastname}")]
+ public IActionResult GetPerson(string firstname, string lastname)
+ {
+ var personToMap = new PersonEntity
+ {
+ FirstName = firstname,
+ LastName = lastname
+ };
+
+ var person = _mapper.Map(personToMap);
+ return new ObjectResult(person);
+ }
+
+ [HttpGet("asset/{assetid}")]
+ public IActionResult GetAsset(string assetid)
+ {
+ var assetToMap = new AssetEntity
+ {
+ Id = assetid
+ };
+
+ var asset = _mapper.Map(assetToMap);
+ return new ObjectResult(asset);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ConfigurationController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ConfigurationController.cs
new file mode 100644
index 0000000..c3fd6fa
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ConfigurationController.cs
@@ -0,0 +1,38 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class ConfigurationController : Controller
+{
+ private readonly IConfiguration _configuration;
+
+ public ConfigurationController(IConfiguration configuration)
+ {
+ _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
+ }
+
+ [HttpGet("environment/{name}")]
+ public IActionResult GetValidEnvironmentConfig(string name)
+ {
+ var configItem = _configuration[name];
+ if (string.IsNullOrWhiteSpace(configItem))
+ return NotFound();
+
+ return Ok(configItem);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ErrorsController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ErrorsController.cs
new file mode 100644
index 0000000..f42b9df
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ErrorsController.cs
@@ -0,0 +1,46 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class ErrorsController : Controller
+{
+ [HttpGet("{data}")]
+ public IActionResult Get(string data)
+ {
+ if (data == "throwFriendly")
+ throw new OurApplicationException();
+ if (data == "throwUnfriendly")
+ throw new Exception("Very bad exception!");
+ if (data == "throwThirdParty")
+ throw new ThirdPartyPluginFailedException();
+ if (data == "throwHierarchy")
+ {
+ var leafException1 = new OurApplicationException("My friendly leaf1!");
+ var leafException2 = new Exception("Security critical super secret!");
+ var leafException4 = new ThirdPartyPluginFailedException();
+ var leafException3 = new Exception("Security critical super secret #2!", leafException4);
+ var aggregate = new AggregateException("Should not see me! (aggregate)", leafException1, leafException2,
+ leafException3);
+ throw new OurApplicationException("Admin root thrown!", aggregate);
+ }
+
+ return new ObjectResult(data);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/FeatureController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/FeatureController.cs
new file mode 100644
index 0000000..8851c22
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/FeatureController.cs
@@ -0,0 +1,21 @@
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class FeatureController : Controller
+{
+ private readonly IFeatureManager _featureManager;
+
+ public FeatureController(IFeatureManager featureManager)
+ {
+ _featureManager = featureManager ?? throw new ArgumentNullException(nameof(featureManager));
+ }
+
+ [HttpGet("{name}")]
+ public async Task GetFeatureAvailability(string name)
+ {
+ if (!await _featureManager.GetFeatureNamesAsync().AnyAsync(m => m == name))
+ return NotFound(false);
+
+ return Ok(await _featureManager.IsEnabledAsync(name));
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/LogsController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/LogsController.cs
new file mode 100644
index 0000000..9ba98e0
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/LogsController.cs
@@ -0,0 +1,41 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class LogsController : Controller
+{
+ public LogsController(ILogger logger)
+ {
+ Log = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ private ILogger Log { get; }
+
+ [HttpGet]
+ public IActionResult Get()
+ {
+ Log.LogTrace("Trace");
+ Log.LogDebug("Debug");
+ Log.LogInformation("Information");
+ Log.LogWarning("Warning");
+ Log.LogError("Error");
+ Log.LogCritical("Critical");
+
+ return Ok();
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ServiceController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ServiceController.cs
new file mode 100644
index 0000000..46c50e6
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ServiceController.cs
@@ -0,0 +1,36 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Core;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class ServiceController : Controller
+{
+ private readonly IMyService _service;
+
+ public ServiceController(IMyService service)
+ {
+ _service = service ?? throw new ArgumentNullException(nameof(service));
+ }
+
+ [HttpGet("{data}")]
+ public string Get(string data)
+ {
+ return _service.Process(data);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValidationController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValidationController.cs
new file mode 100644
index 0000000..b3e8d2e
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValidationController.cs
@@ -0,0 +1,30 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public sealed class ValidationController : Controller
+{
+ [Route("")]
+ [HttpPost]
+ public async Task Post([FromBody] StoreDocumentsRequest request)
+ {
+ return await Task.FromResult(Ok());
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesConsumerController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesConsumerController.cs
new file mode 100644
index 0000000..294beeb
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesConsumerController.cs
@@ -0,0 +1,60 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Core;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class ValuesConsumerController : Controller
+{
+ private readonly IValuesClient _valuesClient;
+
+ public ValuesConsumerController(IValuesClient valuesClient)
+ {
+ _valuesClient = valuesClient ?? throw new ArgumentNullException(nameof(valuesClient));
+ }
+
+ [HttpGet]
+ public async Task> Get()
+ {
+ return await _valuesClient.GetValuesAsync();
+ }
+
+ [HttpGet("{id}")]
+ public async Task Get(int id)
+ {
+ return await _valuesClient.GetValueAsync(id);
+ }
+
+ [HttpPost]
+ public async Task Post([FromBody] string value)
+ {
+ await _valuesClient.GetValuesAsync();
+ }
+
+ [HttpPut("{id}")]
+ public async Task Put(int id, [FromBody] string value)
+ {
+ await _valuesClient.GetValuesAsync();
+ }
+
+ [HttpDelete("{id}")]
+ public async Task Delete(int id)
+ {
+ await _valuesClient.GetValuesAsync();
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesController.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesController.cs
new file mode 100644
index 0000000..19a19a5
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Controllers/ValuesController.cs
@@ -0,0 +1,53 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Controllers;
+
+[Route("api/[controller]")]
+public class ValuesController : Controller
+{
+ // GET api/values
+ [HttpGet]
+ public IEnumerable Get()
+ {
+ return new[] {"value1", "value2"};
+ }
+
+ // GET api/values/5
+ [HttpGet("{id}")]
+ public string Get(int id)
+ {
+ return "value";
+ }
+
+ // POST api/values
+ [HttpPost]
+ public void Post([FromBody] string value)
+ {
+ }
+
+ // PUT api/values/5
+ [HttpPut("{id}")]
+ public void Put(int id, [FromBody] string value)
+ {
+ }
+
+ // DELETE api/values/5
+ [HttpDelete("{id}")]
+ public void Delete(int id)
+ {
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IMyService.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IMyService.cs
new file mode 100644
index 0000000..ef9f6c0
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IMyService.cs
@@ -0,0 +1,22 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core;
+
+public interface IMyService
+{
+ string Process(string param1);
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IValuesClient.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IValuesClient.cs
new file mode 100644
index 0000000..0b6881b
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/IValuesClient.cs
@@ -0,0 +1,35 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core;
+
+public interface IValuesClient : IRestClient
+{
+ [Get("api/Values")]
+ Task> GetValuesAsync();
+
+ [Get("api/Values/{id}")]
+ Task GetValueAsync([Path] int id);
+
+ [Post("api/Values/{id}")]
+ Task PostValueAsync([Path] int id, [Body] string value);
+
+ [Put("api/Values/{id}")]
+ Task PutValueAsync([Path] int id, [Body] string value);
+
+ [Delete("api/Values/{id}")]
+ Task DeleteValueAsync([Path] int id);
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/AssetConverter.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/AssetConverter.cs
new file mode 100644
index 0000000..a2a7d92
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/AssetConverter.cs
@@ -0,0 +1,40 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Mappings;
+
+public sealed class AssetConverter : ITypeConverter
+{
+ private readonly IRateProvider _rateProvider;
+
+ public AssetConverter(IRateProvider rateProvider)
+ {
+ _rateProvider = rateProvider ?? throw new ArgumentNullException(nameof(rateProvider));
+ }
+
+ public AssetDo Convert(AssetEntity source, AssetDo destination, ResolutionContext context)
+ {
+ if (source == null) return null;
+
+ return new AssetDo
+ {
+ Id = source.Id,
+ Rating = _rateProvider.GetRating(source.Id)
+ };
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/DummyRateProvider.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/DummyRateProvider.cs
new file mode 100644
index 0000000..acd8469
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/DummyRateProvider.cs
@@ -0,0 +1,25 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Mappings;
+
+public sealed class DummyRateProvider : IRateProvider
+{
+ public string GetRating(string assetId)
+ {
+ return "AAA";
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/IRateProvider.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/IRateProvider.cs
new file mode 100644
index 0000000..92140db
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Mappings/IRateProvider.cs
@@ -0,0 +1,22 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Mappings;
+
+public interface IRateProvider
+{
+ string GetRating(string assetId);
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/MyService.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/MyService.cs
new file mode 100644
index 0000000..2021bb1
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/MyService.cs
@@ -0,0 +1,25 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core;
+
+public class MyService : IMyService
+{
+ public string Process(string param1)
+ {
+ return $"Processed {param1}";
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/DocumentValidator.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/DocumentValidator.cs
new file mode 100644
index 0000000..f35f057
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/DocumentValidator.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Validators;
+
+public sealed class DocumentValidator : AbstractValidator
+{
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/OwnerValidator.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/OwnerValidator.cs
new file mode 100644
index 0000000..631b3e9
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/OwnerValidator.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Validators;
+
+public sealed class OwnerValidator : AbstractValidator
+{
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/StoreDocumentRequestValidator.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/StoreDocumentRequestValidator.cs
new file mode 100644
index 0000000..2a146a2
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Core/Validators/StoreDocumentRequestValidator.cs
@@ -0,0 +1,52 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Extensions;
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Core.Validators;
+
+public sealed class StoreDocumentRequestValidator : AbstractValidator
+{
+ private readonly HashSet _supportedOperations = new HashSet(new List
+ {
+ "Validate",
+ "Process",
+ "Publish"
+ });
+
+ public StoreDocumentRequestValidator()
+ {
+ RuleFor(m => m.RequestId).NotEmpty();
+ RuleFor(m => m.Operation).Must(OneOfSupportedOperations).WithMessage(GetValidOperationsMessage);
+ RuleFor(c => c.Owner).NotNull().SetValidator(new OwnerValidator());
+ RuleForEach(c => c.Documents).NotNull().NotEmpty().SetValidator(new DocumentValidator());
+ }
+
+ private string GetValidOperationsMessage(StoreDocumentsRequest request)
+ {
+ if (request.Operation.AnyValue())
+ return
+ $"'{request.Operation}' is not supported. Supported operations are: {string.Join(", ", _supportedOperations)}.";
+
+ return $"Operation must be supplied! Supported operations are: {string.Join(", ", _supportedOperations)}.";
+ }
+
+ private bool OneOfSupportedOperations(string operation)
+ {
+ return _supportedOperations.Contains(operation);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetDO.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetDO.cs
new file mode 100644
index 0000000..2939325
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetDO.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class AssetDo
+{
+ public string Id { get; set; }
+ public string Rating { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetEntity.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetEntity.cs
new file mode 100644
index 0000000..8495bd2
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/AssetEntity.cs
@@ -0,0 +1,22 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class AssetEntity
+{
+ public string Id { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Clients.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Clients.cs
new file mode 100644
index 0000000..f4e6b0d
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Clients.cs
@@ -0,0 +1,22 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class Clients
+{
+ public string ProducerClientUrl { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Document.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Document.cs
new file mode 100644
index 0000000..3129df4
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Document.cs
@@ -0,0 +1,22 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class Document
+{
+ public string Path { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/OurApplicationException.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/OurApplicationException.cs
new file mode 100644
index 0000000..039e14a
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/OurApplicationException.cs
@@ -0,0 +1,32 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public sealed class OurApplicationException : TemplateApiApplicationException
+{
+ public OurApplicationException() : base("I am a user friendly exception message")
+ {
+ }
+
+ public OurApplicationException(string message) : base(message)
+ {
+ }
+
+ public OurApplicationException(string message, Exception exception) : base(message, exception)
+ {
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Owner.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Owner.cs
new file mode 100644
index 0000000..8bfe92a
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Owner.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class Owner
+{
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonDO.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonDO.cs
new file mode 100644
index 0000000..878b7e5
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonDO.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class PersonDo
+{
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonEntity.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonEntity.cs
new file mode 100644
index 0000000..c056e73
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/PersonEntity.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class PersonEntity
+{
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section1.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section1.cs
new file mode 100644
index 0000000..3477da1
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section1.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class Section1
+{
+ public string Value1 { get; set; }
+ public string Value2 { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section2.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section2.cs
new file mode 100644
index 0000000..1f162e9
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/Section2.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class Section2
+{
+ public string Value3 { get; set; }
+ public string Value4 { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocuments.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocuments.cs
new file mode 100644
index 0000000..22ec9b8
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocuments.cs
@@ -0,0 +1,23 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class StoreDocuments
+{
+ public Guid RequestId { get; set; }
+ public string StoreOperation { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocumentsRequest.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocumentsRequest.cs
new file mode 100644
index 0000000..3d9f81c
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/StoreDocumentsRequest.cs
@@ -0,0 +1,31 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public class StoreDocumentsRequest
+{
+ public StoreDocumentsRequest()
+ {
+ Documents = new List();
+ }
+
+ public Guid RequestId { get; set; }
+ public string Operation { get; set; }
+
+ public Owner Owner { get; set; }
+ public IEnumerable Documents { get; set; }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/TemplateApiApplicationException.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/TemplateApiApplicationException.cs
new file mode 100644
index 0000000..5b3721f
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/TemplateApiApplicationException.cs
@@ -0,0 +1,28 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public abstract class TemplateApiApplicationException : Exception
+{
+ protected TemplateApiApplicationException(string message) : base(message)
+ {
+ }
+
+ protected TemplateApiApplicationException(string message, Exception exception) : base(message, exception)
+ {
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginException.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginException.cs
new file mode 100644
index 0000000..d73dbcb
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginException.cs
@@ -0,0 +1,24 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public abstract class ThirdPartyPluginException : Exception
+{
+ protected ThirdPartyPluginException(string message) : base(message)
+ {
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginFailedException.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginFailedException.cs
new file mode 100644
index 0000000..7f2ccb4
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Domain/ThirdPartyPluginFailedException.cs
@@ -0,0 +1,24 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+namespace LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+public sealed class ThirdPartyPluginFailedException : ThirdPartyPluginException
+{
+ public ThirdPartyPluginFailedException() : base("Third party plugin has failed!")
+ {
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Extensions/ConfigurationBuilderExtensions.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Extensions/ConfigurationBuilderExtensions.cs
new file mode 100644
index 0000000..fba6467
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Extensions/ConfigurationBuilderExtensions.cs
@@ -0,0 +1,9 @@
+namespace LittleBlocks.Sample.Minimal.WebAPI.Extensions;
+
+public static class ConfigurationBuilderExtensions
+{
+ public static IConfigurationBuilder CustomizeBuilder(this IConfigurationBuilder builder)
+ {
+ return builder ?? throw new ArgumentNullException(nameof(builder));
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/LittleBlocks.Sample.Minimal.WebAPI.csproj b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/LittleBlocks.Sample.Minimal.WebAPI.csproj
new file mode 100644
index 0000000..7fa924e
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/LittleBlocks.Sample.Minimal.WebAPI.csproj
@@ -0,0 +1,37 @@
+
+
+ net8.0
+ False
+ 12
+ enable
+ enable
+ Linux
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+ true
+ PreserveNewest
+
+
+ appsettings.PROD.json
+
+
+
+
+ Always
+
+
+
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Program.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Program.cs
new file mode 100644
index 0000000..1c544d3
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Program.cs
@@ -0,0 +1,100 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using System.Text.Json.Serialization;
+using AutoMapper.Features;
+using FluentValidation.AspNetCore;
+using LittleBlocks.AspNetCore.Documentation;
+using LittleBlocks.AspNetCore.RequestCorrelation;
+using LittleBlocks.Sample.Minimal.WebAPI.Extensions;
+using Serilog;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI;
+
+var builder = WebApplication.CreateBuilder(args);
+
+var applicationInfo = builder.GetApplicationInfo();
+var hostInfo = builder.GetHostInfo();
+var loggingContext = builder.GetLoggingContext();
+
+builder.Host.UseSerilog((context, configuration) => (context, configuration).ConfigureSerilog(loggingContext));
+builder.Services.AddControllers().AddJsonOptions(o =>
+{
+ o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
+}).AddFluentValidation();
+builder.Services.AddValidatorsFromAssemblyContaining();
+
+builder.Services.AddApiVersioning(o =>
+{
+ o.ReportApiVersions = true;
+ o.ApiVersionReader = new MediaTypeApiVersionReader();
+ o.AssumeDefaultVersionWhenUnspecified = true;
+ o.ApiVersionSelector = new CurrentImplementationApiVersionSelector(o);
+});
+
+builder.Services.AddDependencyHealthChecks();
+builder.Services.AddFeatures>(builder.Configuration);
+
+builder.Services
+ .AddSingleton(applicationInfo)
+ .AddRouting(o => o.LowercaseUrls = true)
+ .AddMediatR(typeof(Program))
+ .AddEndpointsApiExplorer()
+ .AddOpenApiDocumentation(applicationInfo)
+ .AddRequestCorrelation()
+ .AddCorsWithDefaultPolicy()
+ .AddTypeMapping(c => c.AddProfile());
+
+var app = builder.Build();
+app.UseRequestCorrelation();
+
+app.UseOpenApiDocumentation(applicationInfo);
+if (!app.Environment.IsDevelopment())
+{
+ app.UseGlobalExceptionAndLoggingHandler();
+ app.UseHsts();
+}
+
+app.UseCors();
+app.UseSerilogRequestLogging(m =>
+{
+ m.IncludeQueryInRequestPath = true;
+ m.EnrichDiagnosticContext = (context, httpContext) => { };
+});
+app.UseHttpsRedirection(hostInfo);
+app.UseAuthorization();
+app.MapDependencyHealthChecks();
+app.MapControllers();
+app.MapStartPage(applicationInfo.Name);
+
+app.Run();
+
+public class Program
+{
+ public static void Main(string[] args)
+ {
+ // HostAsWeb.Run(
+ // builder => builder.CustomizeBuilder(),
+ // s =>
+ // {
+ // if (s.Environment.IsDevelopment() || s.Environment.IsEnvironment("INT"))
+ // return s.ConfigureLogger(c => c.UseSeq(s.Configuration.GetSection("Logging:Seq")));
+ //
+ // return s.ConfigureLogger(c =>
+ // c.UseLoggly(s.Configuration.GetSection("Logging:Loggly")));
+ // }, args);
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Startup.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Startup.cs
new file mode 100644
index 0000000..406678a
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Startup.cs
@@ -0,0 +1,80 @@
+// This software is part of the LittleBlocks framework
+// Copyright (C) 2024 LittleBlocks
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+using LittleBlocks.Sample.Minimal.WebAPI.Core;
+using LittleBlocks.Sample.Minimal.WebAPI.Core.Mappings;
+using LittleBlocks.Sample.Minimal.WebAPI.Domain;
+
+namespace LittleBlocks.Sample.Minimal.WebAPI;
+
+public class Startup
+{
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ private IConfiguration Configuration { get; }
+
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.BootstrapApp(Configuration,
+ app => app
+ .AddConfigSection()
+ .AndSection()
+ .AndSection()
+ .HandleApplicationException()
+ .ConfigureCorrelation(m => m.AutoCorrelateRequests())
+ .ConfigureHealthChecks(c =>
+ {
+ c.AddUrlGroup(new Uri("http://www.google.com"), HttpMethod.Get, "google");
+ c.AddUrlGroup(new Uri("http://www.Microsoft.com"), HttpMethod.Get, "microsoft");
+ c.AddUrlGroup(new Uri("https://github.com/littleblocks"), HttpMethod.Get, "LittleBlocks");
+ c.AddSeqPublisher(setup =>
+ {
+ setup.Endpoint = Configuration["Logging:Seq:ServerUrl"];
+ setup.ApiKey = Configuration["Logging:Seq:ApiKey"];
+ });
+ })
+ .ConfigureMappings(c =>
+ {
+ c.CreateMap();
+ c.CreateMap().ConvertUsing();
+ })
+ .AddServices((container, config) =>
+ {
+ container.AddRestClient(c => c.ProducerClientUrl);
+ container.AddTransientWithInterception(by =>
+ by.InterceptBy());
+ container.AddTransientWithInterception(by =>
+ by.InterceptBy());
+ container.AddSingleton, AssetConverter>();
+ services
+ .AddHealthChecksUI()
+ .AddInMemoryStorage();
+ })
+ );
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
+ {
+ app.UseDefaultApiPipeline(Configuration, env, loggerFactory);
+ app.UseEndpoints(config =>
+ {
+ config.MapHealthChecksUI(m => m.AddCustomStylesheet("health-ui.css"));
+ });
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Usings.cs b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Usings.cs
new file mode 100644
index 0000000..3f5bafb
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/Usings.cs
@@ -0,0 +1,27 @@
+global using System;
+global using System.Linq;
+global using System.Threading.Tasks;
+global using System.Collections.Generic;
+global using System.Net.Http;
+global using LittleBlocks.RestEase.Client;
+global using LittleBlocks.AspNetCore;
+global using LittleBlocks.Logging.SeriLog.Loggly;
+global using LittleBlocks.Logging.SeriLog.Seq;
+global using LittleBlocks.AspNetCore.Bootstrap;
+global using LittleBlocks.AspNetCore.Bootstrap.Extensions;
+global using LittleBlocks.AspNetCore.Logging.SeriLog;
+global using LittleBlocks.RestEase;
+global using Microsoft.Extensions.Hosting;
+global using Microsoft.AspNetCore.Authorization;
+global using Microsoft.AspNetCore.Mvc;
+global using Microsoft.Extensions.Logging;
+global using Microsoft.Extensions.Configuration;
+global using Microsoft.FeatureManagement;
+global using Microsoft.AspNetCore.Builder;
+global using Microsoft.AspNetCore.Hosting;
+global using Microsoft.Extensions.DependencyInjection;
+
+global using AutoMapper;
+global using FluentValidation;
+global using RestEase;
+global using Foil;
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.Development.json b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.Development.json
new file mode 100644
index 0000000..7755d7f
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.Development.json
@@ -0,0 +1,15 @@
+{
+ "Logging": {
+ "IncludeScopes": false,
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ },
+ "Seq": {
+ "ServerUrl": "http://localhost:8089",
+ "ApiKey": "pb6zPcoknbcRdKu2VtqL",
+ "AllowLogLevelToBeControlledRemotely": true
+ }
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.json b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.json
new file mode 100644
index 0000000..31b00b8
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/appsettings.json
@@ -0,0 +1,72 @@
+{
+ "Logging": {
+ "IncludeScopes": false,
+ "LogFilePath": "",
+ "Serilog": {
+ "MinimumLevel": "Trace"
+ },
+ "Loggly": {
+ "IsEnabled": "false",
+ "ServerUrl": "https://logs-01.loggly.com/",
+ "CustomerToken": "LogglyCustomerToken",
+ "BufferBaseFilename": "logs\\loggly-buffer",
+ "NumberOfEventsInSingleBatch": 50,
+ "BatchPostingIntervalInSeconds": 2,
+ "EventBodyLimitKb": 10,
+ "RetainedInvalidPayloadsLimitMb": 100,
+ "AllowLogLevelToBeControlledRemotely": false
+ },
+ "Seq": {
+ "ServerUrl": "http://localhost:8089",
+ "ApiKey": "pb6zPcoknbcRdKu2VtqL",
+ "AllowLogLevelToBeControlledRemotely": true
+ }
+ },
+ "ApplicationInsights": {
+ "InstrumentationKey": "Instrument Key Here"
+ },
+ "AuthOptions": {
+ "AuthenticationMode": "OAuth2",
+ "Authentication": {
+ "Authority": "https://login.microsoftonline.com/31d4ce72-dfb2-4be8-b876-3278f8641754",
+ "Audience": "f7748175-fc0b-4982-8539-070199f3e768"
+ }
+ },
+ "HealthChecksUI": {
+ "HealthChecks": [
+ {
+ "Name": "API health endpoint",
+ "Uri": "https://localhost:5001/health"
+ }
+ ],
+ "Webhooks": [],
+ "EvaluationTimeinSeconds": 10,
+ "MinimumSecondsBetweenFailureNotifications": 60
+ },
+ "Application": {
+ "Name": "Sample API",
+ "Version": "1.0",
+ "Url": "",
+ "Environment": {
+ "Name": "Integration",
+ "Prefix": "int"
+ }
+ },
+ "Section1": {
+ "Value1": "1",
+ "Value2": "2"
+ },
+ "Section2": {
+ "Value3": "3",
+ "Value4": "4",
+ "Section3": {
+ "Value1": "1",
+ "Value2": "2",
+ "Value3": "3",
+ "Value4": "4"
+ }
+ },
+ "Clients": {
+ "ProducerClientUrl": "https://localhost:5001/"
+ }
+}
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/health-ui.css b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/health-ui.css
new file mode 100644
index 0000000..5c10e01
--- /dev/null
+++ b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/health-ui.css
@@ -0,0 +1,8 @@
+:root {
+ --primaryColor: #192544;
+ --secondaryColor: #f4f4f4;
+ --bgMenuActive: #3f5a9a;
+ --bgButton: #2c4272;
+ --bgAside: var(--primaryColor);
+ --logoImageUrl: url('sample.png');
+}
\ No newline at end of file
diff --git a/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/sample.png b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/sample.png
new file mode 100644
index 0000000..c8db6c8
Binary files /dev/null and b/src/Samples/LittleBlocks.Sample.MinimalApi..WebAPI/sample.png differ