Modern Architecture Shop is a clean-lightweight .NET Microservices application. Here I will demonstrate the use of Dapr to build Microservices-based applications.
Open Invitation - Any developer is welcome to join our team! Just send me a request.
The application UI


The implemented application architect is still based on the classic Microservices architectural style; we have a collection of DDD-services, which are working together to build the system.
The diagram above is created with Draw.io. Draw.io is a free online diagram software.
Roadmap
- Finishing the Order and Payment services.
- The first challenge is scaling the application out. I give an example which provides Proof of the Concept for containers scaling and testing the system with Chaos Monkey Tests.
- Changing the services to Actors with a scaling concept.
- Finally, using KEDA. KEDA is a Kubernetes-based Event-Driven Autoscaler (Horizontal Pod Autoscaler)
Modern Architecture Shop on GitHub - ModernArchitectureShop
- In this version, I have done more clean architecture and clean code stuff:
- I have separated the application from the Infrastructure.
- Use Cases are moved into the application.
- The Persistence abstraction moved to the application.
In the example below, you can see that the Store application contains the business logic abstraction.

The framework's references moved to the infrastructure assembly. If you remember in a previous article, our main goal was to make the infrastructure depending on the application.
In addition, I have added the order of domain events. These events are working together on the use cases to build a single coherent system.
ProcessOrder Event
The event is fired when the user clicks on the buy button.
PayOrder Event
This event creates the order so that it can be sent to the Payment Service. After that, the payment can succeed or fail.
PrdocutsSold Event
The event is fired when the payment is successful. This event helps to update the products availability in the Store.
PaymentConfirmed Event
The event is fired when the payment has been successful. This event is responsible to remove the processed order and basket information.
PaymentFailed Event
The event is fired when the payment fails. This event is used to remove the failed order data and to reactivate the buy state in the Basket service.
ModernArchitectureShop.ShopUI

As you see in the image above, I have selected ProductsService and ProductsDaprClient, these two classes are equivalent, both are calling the Store API, but they are using two different approaches, the Product API is using HTTPClient to call the Store API and the other one is using DaprCilent.
- public class ProductsService
- {
- private readonly HttpClient _storeHttpClient;
- private readonly IHttpContextAccessor _httpContextAccessor;
- public ProductsService(HttpClient storeHttpClient, IHttpContextAccessor httpContextAccessor)
- {
- _storeHttpClient = storeHttpClient ?? throw new ArgumentNullException(nameof(storeHttpClient));
- _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
- }
- public async Task AttachAccessTokenToHeader()
- {
- var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
- if (accessToken != null)
- {
- var auth = _storeHttpClient.DefaultRequestHeaders.Authorization?.Parameter;
- if (auth == null)
- _storeHttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
- }
- }
- public async Task<ServiceResult<string>> SearchProducts(string url)
- {
- await AttachAccessTokenToHeader();
- HttpResponseMessage response;
- try
- {
- response = await _storeHttpClient.GetAsync(url);
- response.EnsureSuccessStatusCode();
- }
- catch (HttpRequestException e)
- {
- return new ServiceResult<string>
- {
- Content = null!,
- StatusCode = 500, // Server Error!
- Error = e.Message
- };
- }
- return new ServiceResult<string>
- {
- Content = await response.Content.ReadAsStringAsync(),
- StatusCode = (int)response.StatusCode,
- Error = string.Empty
- };
- }
- public async Task<ServiceResult<string>> GetProductsAsync(string url)
- {
- await AttachAccessTokenToHeader();
- HttpResponseMessage response;
- try
- {
- response = await _storeHttpClient.GetAsync(url);
- response.EnsureSuccessStatusCode();
- }
- catch (HttpRequestException e)
- {
- return new ServiceResult<string>
- {
- Content = null!,
- StatusCode = 500, // Server Error!
- Error = e.Message
- };
- }
- return new ServiceResult<string>
- {
- Content = await response.Content.ReadAsStringAsync(),
- StatusCode = (int)response.StatusCode,
- Error = string.Empty
- };
- }
- }

Join the conversation! Your thoughts help the community grow.