In this post, I will outline an application using .NET 8 and MongoDB. The goal was not just to create another demo application, but to explore how these technologies can work together to create a modular system with clean architecture principles, repository patterns, and NoSQL database integration.
Introduction
This blog post explores the development of a system built with .NET 8 and MongoDB. This application provides core functionalities including account creation, money transfers between accounts, deposits, withdrawals, and transaction history tracking.
The application demonstrates modern software development practices including:
- Clean architecture with separation of concerns
- Domain-driven design principles
- Repository pattern for data access
- Dependency injection
- Validation using FluentValidation
- Comprehensive unit testing
- API documentation with Swagger/OpenAPI
- NoSQL database integration with MongoDB
Whether you're learning about .NET development, exploring MongoDB integration, or interested in modern application architecture, this project provides valuable insights into building modular and maintainable applications.
Technologies Used
Core Technologies
- .NET 8: The latest version of Microsoft's cross-platform development framework
- ASP.NET Core Web API: For building RESTful APIs
- MongoDB: A NoSQL document database for flexible data storage
- MongoDB.Driver: The official C# driver for MongoDB
Libraries and Tools
- FluentValidation: For robust request validation
- Swagger/OpenAPI: For API documentation and testing
- xUnit: For unit testing
- Moq: For mocking dependencies in tests
- Docker: For containerization of MongoDB
Architecture Overview
The system follows a clean, layered architecture that promotes separation of concerns, testability, and maintainability. The application is divided into four main projects:
- BankAccountManagement.API: The presentation layer containing controllers, DTOs, and validators
- BankAccountManagement.Core: The domain layer with business entities, interfaces, and services
- BankAccountManagement.Infrastructure: The data access layer with MongoDB integration
- BankAccountManagement.Tests: Unit tests for all components
Architecture Diagram
┌───────────────────────────────────────────────────────────────────────────┐
│ Client Applications │
└──────────────────────────────────▲────────────────────────────────────────┘
│
│
┌──────────────────────────────────▼─────────────────────────────────────────┐
│ BankAccountManagement.API │
│ │
│ ┌──────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ Controllers │ │ DTOs │ │ Validators │ │
│ │ │ │ │ │ │ │
│ │ AccountsCtrl │ │ AccountDto │ │ CreateAccountValidator │ │
│ │ TransactionsCtrl │ │ TransactionDto │ │ TransferValidator │ │
│ │ │ │ DepositDto │ │ DepositValidator │ │
│ │ │ │ WithdrawDto │ │ WithdrawValidator │ │
│ └──────────────────┘ └─────────────────┘ └─────────────────────────┘ │
└───────────────────────────────────▲────────────────────────────────────────┘
│
│
┌───────────────────────────────────▼────────────────────────────────────────┐
│ BankAccountManagement.Core │
│ │
│ ┌─────────────────┐ ┌───────────────────┐ ┌────────────────────────┐ │
│ │ Entities │ │ Interfaces │ │ Services │ │
│ │ │ │ │ │ │ │
│ │ Account │ │ IRepository │ │ AccountService │ │
│ │ Transaction │ │ IAccountRepo │ │ TransactionService │ │
│ │TransactionStatus│ │ ITransactionRepo │ │ │ │
│ │ │ │ IAccountService │ │ │ │
│ │ │ │ITransactionService│ │ │ │
│ └─────────────────┘ └───────────────────┘ └────────────────────────┘ │
└───────────────────────────────────▲────────────────────────────────────────┘
│
│
┌───────────────────────────────────▼────────────────────────────────────────┐
│ BankAccountManagement.Infrastructure │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────────────┐ │
│ │ Repositories │ │ Data Context │ │ Configuration │ │
│ │ │ │ │ │ │ │
│ │ BaseRepository │ │ MongoDbContext │ │ MongoDbSettings │ │
│ │ AccountRepo │ │ │ │ │ │
│ │ TransactionRepo│ │ │ │ │ │
│ └────────────────┘ └────────────────┘ └────────────────────────┘ │
└─────────────────────────────────▲──────────────────────────────────────────┘
│
│
┌─────────────────────────────────▼──────────────────────────────────────────┐
│ MongoDB Database │
│ │
│ ┌────────────────────────┐ ┌────────────────────────┐ │
│ │ Accounts │ │ Transactions │ │
│ │ Collection │ │ Collection │ │
│ └────────────────────────┘ └────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
</pre>
Domain Models
The system revolves around two primary domain entities:
Account
public class Account
{
public string Id { get; set; }
public string AccountName { get; set; }
public decimal Balance { get; set; }
}
Transaction
public class Transaction
{
public string Id { get; set; }
public string FromAccountId { get; set; }
public string ToAccountId { get; set; }
public decimal Amount { get; set; }
public DateTime Timestamp { get; set; }
public string Description { get; set; }
public TransactionStatus Status { get; set; }
}
public enum TransactionStatus
{
Pending,
Completed,
Failed
}
API Endpoints
The system exposes the following RESTful API endpoints:
Account Endpoints
GET /api/accounts - Get all accounts
GET /api/accounts/{id} - Get account by ID
POST /api/accounts - Create new account
Transaction Endpoints
GET /api/transactions/account/{accountId} - Get transactions for an account
POST /api/transactions/transfer - Transfer money between accounts
POST /api/transactions/account/{accountId}/deposit - Deposit money into an account
POST /api/transactions/account/{accountId}/withdraw - Withdraw money from an account
Key Implementation Features
Repository Pattern
The system uses the repository pattern to abstract data access operations:
public interface IRepository where T : class
{
Task<IEnumerable> GetAllAsync();
Task GetByIdAsync(string id);
Task AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(string id);
}</code></pre>
Validation with FluentValidation
Request validation is implemented using FluentValidation:
public class TransferDtoValidator : AbstractValidator
{
public TransferDtoValidator()
{
RuleFor(x => x.FromAccountId)
.NotEmpty().WithMessage("Source account ID is required");
RuleFor(x => x.ToAccountId)
.NotEmpty().WithMessage("Destination account ID is required")
.NotEqual(x => x.FromAccountId).WithMessage("Source and destination accounts must be different");
RuleFor(x => x.Amount)
.NotEmpty().WithMessage("Amount is required")
.GreaterThan(0).WithMessage("Amount must be greater than zero");
}
}</code></pre>
Comprehensive Testing
The system includes extensive unit tests for all components:
[Fact]
public async Task TransferAsync_WithInsufficientBalance_ShouldThrowInvalidOperationException()
{
// Arrange
var fromAccountId = "1";
var toAccountId = "2";
var amount = 1000m;
var description = "Test transfer";
var fromAccount = new Account { Id = fromAccountId, AccountName = "Source Account", Balance = 500 };
var toAccount = new Account { Id = toAccountId, AccountName = "Destination Account", Balance = 200 };
_mockAccountRepository.Setup(repo => repo.GetByIdAsync(fromAccountId))
.ReturnsAsync(fromAccount);
_mockAccountRepository.Setup(repo => repo.GetByIdAsync(toAccountId))
.ReturnsAsync(toAccount);
// Act & Assert
await Assert.ThrowsAsync(() =>
_transactionService.TransferAsync(fromAccountId, toAccountId, amount, description));
}</code></pre>
MongoDB Integration
The system integrates with MongoDB using the official MongoDB.Driver:
public class MongoDbContext
{
private readonly IMongoDatabase _database;
public MongoDbContext(IOptions settings)
{
var client = new MongoClient(settings.Value.ConnectionString);
_database = client.GetDatabase(settings.Value.DatabaseName);
}
public IMongoCollection Accounts => _database.GetCollection("Accounts");
public IMongoCollection Transactions => _database.GetCollection("Transactions");
}</code></pre>
GitHub Repository
The complete source code for this project is available on GitHub:
https://github.com/aamersadiq/dotnet-mongodb
Conclusion
This project demonstrates how to build a well-structured application using .NET 8 and MongoDB. By following clean architecture principles and implementing proper separation of concerns, the system is maintainable, testable, and extensible.
Key takeaways from this project include:
- Structuring a .NET application with clean architecture
- Implementing the repository pattern with MongoDB
- Using FluentValidation for request validation
- Building comprehensive unit tests
- Documenting APIs with Swagger/OpenAPI
- Implementing proper validation with FluentValidation
Whether you're building a banking system or any application that requires structured data management, the patterns and practices demonstrated in this project provide a solid foundation for your development efforts.