A comprehensive contact management system built with ASP.NET Core 8.0 MVC, demonstrating modern web development practices, clean architecture, and advanced Entity Framework Core features.
This application provides a full-featured contact management system with Create, Read, Update, and Delete (CRUD) operations. It showcases professional-grade development practices including repository pattern, dependency injection, comprehensive testing, and multiple data export formats.
- Complete CRUD Operations: Create, read, update, and delete person records
- Advanced Search: Filter persons by name, email, date of birth, gender, country, or address
- Dynamic Sorting: Sort by any field in ascending or descending order using reflection
- Country Management: Manage and associate countries with persons
- Data Validation: Custom validation attributes and model validation
- PDF Export: Generate PDF reports using Rotativa
- Excel Export: Create Excel files using EPPlus
- CSV Export: Export data to CSV format using CsvHelper
- Repository Pattern: Clean separation of data access logic
- Dependency Injection: Loosely coupled, testable architecture
- Entity Framework Core: Code-first approach with migrations
- Stored Procedures: Custom SQL Server stored procedures for complex operations
- Fluent API: Advanced entity configuration with constraints and relationships
- Custom Validations: Add validation and other business rules
The application follows a multi-layered architecture for separation of concerns:
Contacts-Manager-CRUD/ # Web Layer (MVC)
βββ Controllers/ # HTTP request handlers
βββ Views/ # Razor views
βββ wwwroot/ # Static files
Entities/ # Domain Layer
βββ Person.cs # Person entity
βββ Country.cs # Country entity
βββ PersonsDbContext.cs # Database context
βββ Migrations/ # EF Core migrations
ServiceContracts/ # Application Layer Contracts
βββ IPersonsService.cs # Person service interface
βββ ICountriesService.cs # Country service interface
βββ DTO/ # Data Transfer Objects
βββ Enums/ # Application enumerations
βββ Validations/ # Custom validation attributes
Services/ # Application Layer Implementation
βββ PersonsService.cs # Business logic for persons
βββ CountriesService.cs # Business logic for countries
βββ Helpers/ # Helper utilities
RepositoryContracts/ # Data Access Contracts
βββ IPersonsRepository.cs # Person repository interface
βββ ICountriesRepository.cs # Country repository interface
Repository/ # Data Access Implementation
βββ PersonsRepository.cs # Data access for persons
βββ CountriesRepository.cs # Data access for countries
xUnitTests/ # Test Layer
βββ PersonsServiceTest.cs # Unit tests
βββ CountriesServiceTest.cs # Unit tests
βββ PersonsControllerTest.cs # Controller tests
βββ PersonsControllerIntegrationTest.cs # Integration tests
.NET 8.0, ASP.NET Core MVC, C# 12, Entity Framework Core, SQL Server
Microsoft.EntityFrameworkCore.Design 9.0.8- EF Core design-time toolsMicrosoft.EntityFrameworkCore.SqlServer 9.0.8- SQL Server providerRotativa.AspNetCore 1.4.0- PDF generation from HTML
Microsoft.EntityFrameworkCore.SqlServer 9.0.8- Database providerMicrosoft.EntityFrameworkCore.Tools 9.0.8- Migration tools
CsvHelper 33.1.0- CSV file handlingEPPlus 8.2.1- Excel file generation
xUnit 2.5.3- Testing frameworkMoq 4.20.72- Mocking frameworkAutoFixture 4.18.1- Test data generationFluentAssertions 8.8.0- Fluent assertion libraryEntityFrameworkCoreMock.Moq 2.4.0- EF Core mockingMicrosoft.EntityFrameworkCore.InMemory 9.0.8- In-memory database for testingMicrosoft.AspNetCore.Mvc.Testing 8.0.22- Integration testingFizzler.Systems.HtmlAgilityPack 1.2.1- HTML parsing for view testing
- Repository Pattern: Abstracts data access logic
- Dependency Injection: Constructor-based DI throughout
- DTO Pattern: Separation of domain models and data transfer objects
- Service Layer Pattern: Business logic isolated from controllers
- Code-First Migrations: Version-controlled database schema
- Fluent API: Advanced entity configuration
- Check constraints (e.g., PIN length validation)
- Custom column types
- Relationships and foreign keys
- Stored Procedures: Custom SQL procedures for complex queries
- Include/ThenInclude: Eager loading of related entities
- Expression Trees: Dynamic LINQ queries in repositories
- Data Seeding: Initial data from JSON files
Instead of lengthy switch statements, the application uses reflection for dynamic property sorting:
// Dynamic sorting using reflection
var sortByProperty = typeof(PersonResponse).GetProperty(sortBy,
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);Benefits: More maintainable, works with new properties without code changes
Custom DateCheckerAttribute ensures users are at least 18 years old:
[DateChecker] // Validates minimum age requirement
public DateTime? DateOfBirth { get; set; }Centralized model validation using the ValidationHelper class for consistent error handling across services.
- Service Layer Tests: Mock repositories with Moq
- AutoFixture: Automatic test data generation
- FluentAssertions: Readable test assertions
- Isolation: Each test is independent with mocked dependencies
- WebApplicationFactory: Full application testing
- In-Memory Database: Fast test database
- Custom Factory:
CustomWebApplicationFactoryfor test configuration - HTML Parsing: Fizzler for view testing
- PersonsService tests
- CountriesService tests
- PersonsController tests
- End-to-end integration tests
- PersonId (Guid, Primary Key)
- PersonName (String, max 45 chars)
- Email (String, max 30 chars)
- DateOfBirth (DateTime, nullable)
- Gender (String, max 10 chars)
- CountryId (Guid, Foreign Key, nullable)
- Address (String, max 65 chars)
- ReceiveNewsLettter (Boolean, nullable)
- PIN (String, varchar(6) with check constraint)
- CountryID (Guid, Primary Key)
- CountryName (String)
The application includes multiple migrations demonstrating database evolution:
- Initial schema creation
- Adding stored procedures (GetAllPersons, InsertPerson)
- Adding PIN column
- Updating stored procedures for new columns
- Adding check constraints
GetAllPersons: Retrieves all persons with country informationInsertPerson: Inserts a new person record
-
Clone the repository
git clone https://github.com/<your-username>/Contacts-Manager-CRUD-aspnet-core.git cd Contacts-Manager-CRUD-aspnet-core
Note: Replace
<your-username>with the actual repository owner's username. -
Restore dependencies
dotnet restore
-
Update the connection string (if needed)
Edit
Contacts-Manager-CRUD/appsettings.json:"ConnectionStrings": { "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=ContactsManagerDB;..." }
-
Apply database migrations
dotnet ef database update --project Entities --startup-project Contacts-Manager-CRUD
-
Run the application
cd Contacts-Manager-CRUD dotnet run -
Access the application
Open your browser and navigate to
https://localhost:5001orhttp://localhost:5000
Run all tests:
dotnet testRun specific test project:
dotnet test xUnitTests/xUnitTests.csprojRun with detailed output:
dotnet test --verbosity detailed- PersonsController: Handles person CRUD operations, search, sort, and export
- CountriesController: Manages country data and Excel upload
- PersonsService: Business logic for person management
- CountriesService: Business logic for country management
- ValidationHelper: Centralized model validation
- PersonAddRequest: DTO for creating a person
- PersonUpdateRequest: DTO for updating a person
- PersonResponse: DTO for returning person data
- CountryAddRequest: DTO for adding a country
- CountryResponse: DTO for returning country data
- GenderOptions: Enumeration for gender values
- SortOrderOptions: ASC/DESC sorting options
- DateCheckerAttribute: Custom validation for minimum age (18 years)
The application uses Razor views with:
- _Layout.cshtml: Master layout template
- Index.cshtml: Person list with search and sort
- Create.cshtml: Form for adding new persons
- PersonsPDF.cshtml: PDF report template
- _GridColumnHeader.cshtml: Reusable column header partial
Non-commercial license configured in Program.cs:
ExcelPackage.License.SetNonCommercialPersonal("<YourName>");Note: Replace <YourName> with your actual name/identifier for non-commercial use.
PDF generation configured with wkhtmltopdf:
RotativaConfiguration.Setup("wwwroot", wkhtmltopdfRelativePath: "Rotativa");Services registered in Program.cs:
- DbContext with SQL Server provider
- Repository implementations
- Service implementations
This project demonstrates:
- Clean architecture principles
- Repository pattern implementation
- Comprehensive unit and integration testing
- Entity Framework Core advanced features
- Custom validation attributes
- Dependency injection best practices
- Reflection for dynamic behavior
- Expression trees for flexible queries
- Multiple export format generation
- Stored procedure integration
- Database migrations and seeding
This is a learning project. Feel free to fork and experiment with your own enhancements.
Built with ASP.NET Core 8.0 MVC