From Concept to Code: Learning Modern .NET with eShop
The .NET eShop project is a comprehensive reference application designed by Microsoft. It showcases modern software development practices using the .NET framework. For a software engineer, it’s not just an example; it's a valuable learning tool and a starting point for building robust, scalable, and maintainable applications. It's an eCommerce site, but the real value lies in the architectural patterns and technologies it demonstrates, not just the business domain.
The eShop project is useful because it provides a practical, real-world example of how to implement various architectural patterns and technologies.
Microservices Architecture
It’s a prime example of a microservices-based system. You can see how different business domains (like catalog, ordering, and basket) are broken down into separate, independently deployable services. This is invaluable for understanding the challenges and benefits of this architectural style, such as inter-service communication, data consistency, and service discovery.
Domain-Driven Design (DDD)
The code is structured around business domains, a key tenet of DDD. You can learn how to define bounded contexts, aggregates, and entities, which leads to cleaner, more understandable code that is easier to maintain and evolve.
Asynchronous Communication
It uses RabbitMQ for event-driven, asynchronous communication between services. This is a critical pattern for decoupling services and improving system resilience. You can study how events are published and consumed, and how this helps in avoiding tight dependencies.
Cloud-Native Principles
The application is built to be deployed to the cloud, specifically Azure Kubernetes Service (AKS). It demonstrates containerization with Docker, orchestration with Kubernetes, and how to use cloud services for things like caching (Redis) and persistence (SQL Server).
API Management
It uses API Gateways (Ocelot) to unify multiple microservices into a single entry point for clients, which simplifies client-side development and provides a central point for cross-cutting concerns like authentication and rate limiting.
Getting the eShop project up and running is straightforward. Here’s a basic step-by-step guide.
Prerequisites
Make sure you have the following installed
Git
To clone the repository.
Docker Desktop
The project uses Docker to run all the services and databases.
.NET SDK
You’ll need the latest version of the .NET SDK (e.g., .NET 8) to build the projects.
Visual Studio Code or Visual Studio
An IDE is essential for navigating the code.
Clone the Repository
Open your terminal or command prompt and clone the official repository from GitHub.
git clone https://github.com/dotnet/eShop.git
cd eShop
Run with Docker
The easiest way to get everything running is by using Docker Compose. This command will build and start all the services, including the databases and message broker, in a single go.
docker-compose -f docker-compose.yml up --build
This command can take a few minutes as it downloads and builds all the images. Once it's done, you'll have a fully functional eShop running locally.
Explore the Application
Once the containers are running, you can access the various parts of the application
The web application (the front end) is usually available at http://localhost:5100.
The API Gateway is typically at http://localhost:5202.
Let's dive into a small part of the code to see how it's structured. We'll look at the Catalog API, which is a microservice responsible for managing product information.
Here’s a simplified look at a controller action within the Catalog.API project, specifically the CatalogController.
// Inside src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs
[HttpGet]
[Route("items")]
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> ItemsAsync([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null)
{
if (!string.IsNullOrEmpty(ids))
{
var items = await _catalogContext.CatalogItems.Where(i => ids.Contains(i.Id.ToString())).ToListAsync();
return Ok(items);
}
// Logic to paginate items
var totalItems = await _catalogContext.CatalogItems.LongCountAsync();
var itemsOnPage = await _catalogContext.CatalogItems
.OrderBy(c => c.Name)
.Skip(pageSize * pageIndex)
.Take(pageSize)
.ToListAsync();
return Ok(new PaginatedItemsViewModel<CatalogItem>(pageIndex, pageSize, totalItems, itemsOnPage));
}
This simple controller method demonstrates a few key things
API Endpoints
It exposes a GET endpoint at /items to fetch catalog products.
Dependency Injection
The _catalogContext (an ApplicationDbContext from Entity Framework Core) is injected into the controller, which is a standard .NET practice for accessing data.
Asynchronous Operations
The use of async and await ensures that the database calls don't block the thread, which is crucial for building high-performance APIs.
Repository Pattern
Although not explicitly shown in this snippet, the project often uses the repository pattern to abstract the data access logic.