A full-stack ASP.NET Core web application for managing and importing card game decks with a layered architecture, unit tests, and CI/CD pipeline. Created with the initial motivation of inspiring deck-building creativity by enabling me to see which cards I have yet to include in decks.
| Layer | Technology |
|---|---|
| Framework | ASP.NET Core 8+ MVC |
| ORM | Entity Framework Core |
| Database | SQLite |
| Testing | xUnit, Moq |
| Frontend | Razor Views, HTML5, CSS3 |
| CI/CD | GitHub Actions |
CardTrackerWeb/
├── CardTrackerWebMainProj/
│ ├── Controllers/ # HTTP request handlers
│ ├── BLL/ (Business Logic Layer)
│ │ ├── Interfaces/
│ │ └── Services/
│ ├── DAL/ (Data Access Layer)
│ │ ├── Interfaces/
│ │ └── Repositories/
│ ├── Models/ # Domain entities
│ ├── Data/ # EF Core DbContext
│ ├── Views/ # Razor templates
│ └── Program.cs # DI configuration & app setup
│
└── CardTrackerWeb.Tests/ # Unit test project
- Presentation Layer: Controllers + Razor Views handle HTTP requests/responses
- Business Logic Layer: Services encapsulate business rules and workflows
- Data Access Layer: Repositories abstract database operations via EF Core
All services registered in Program.cs using ASP.NET Core's built-in DI container:
builder.Services.AddScoped<ICardService, CardService>();
builder.Services.AddScoped<IDeckService, DeckService>();
builder.Services.AddSingleton<ICardListParser, ThronesDbJsonCardListParser>();ICardListParser- Parses card data from external JSON sourcesIDeckImporter- Imports deck lists from user-provided text formatICardService/IDeckService- Business logic for cards and decksICardRepo/IDeckRepo- Database persistence abstraction
- ✅ Create, read, update, and delete decks
- ✅ Full deck composition visibility with card details
- ✅ Persistent storage with SQLite
- ✅ Parse ThronesDB
.txtdeck format - ✅ Validate and normalize imported card data
- ✅ Handle import errors with meaningful feedback
- ✅ Load card metadata from ThronesDB JSON API
- ✅ Card search and filtering by faction
- .NET 8 SDK or later
- SQLite
-
Clone the repository
git clone {this repository} cd CardTrackerWeb -
Restore dependencies
dotnet restore
-
Run the application
cd CardTrackerWebMainProj dotnet runThe app will automatically seed the database on first run.
-
Open in browser
https://localhost:5001
# Run all tests
dotnet test
# Run with verbose output
dotnet test --verbosity detailed
# Run specific test class
dotnet test --filter "ClassName=DeckServiceTests"- Navigate to Decks → Import
- Paste a ThronesDB deck list (
.txtformat) - Application validates format and imports cards
- View imported deck in Decks list with full composition
- View: Click a deck to see all cards, constraints, and metadata
- Edit: Update deck name and description
- Delete: Permanently remove a deck
- Service isolation: Mocked repositories and dependencies using Moq
- Happy path: Successful deck import with valid data
- Error cases: Unknown faction, missing cards, validation failures
- Verification: Assert that repositories receive correct data
Example:
[Test]
public async Task ImportDeck_WhenImporterParsesDeckString_ShouldReturnSuccessWithId()
{
// Arrange
var mockRepo = new Mock<IDeckRepo>();
var deckService = new DeckService(mockRepo.Object, ...);
// Act
var result = await deckService.ImportDeckFromString("deck string", "owner", "name");
// Assert
Assert.That(result.Status, Is.EqualTo(DeckImportStatus.Success));
mockRepo.Verify(r => r.InsertDeck(It.IsAny<Deck>()), Times.Once);
}- Nullable field handling (cost, strength, etc.)
- Complete card property coverage
- Service layer: Business logic and workflows
- Parser layer: JSON deserialization and validation
- Edge cases: Null values, invalid data, missing resources
Update appsettings.json for database and API settings:
{
"ConnectionStrings": {
"LocalSQLiteCardTrackerDb": "Data Source=cardtracker.db"
}
}SQLite database file will be created automatically on first run.
GitHub Actions automatically:
- ✅ Builds the solution
- ✅ Runs all unit tests
- ✅ Reports test coverage
- ✅ Validates code style
View workflow: .github/workflows/dotnet.yml
- ThronesDB API - Card data fetched on application startup (requires internet)
- SQLite - Local database stored in project directory
- Schema created model-first by EF Core. Migrations can be found in CardTrackerWebMainProj/Migrations
- Seeding happens during application initialization