Eight modules have built, piece by piece, a complete library management system called
BiblioTech: from the first "Hello World" and the variables of Module 1, through the
object-oriented domain model (LibraryItem, Book, Magazine, Member, Loan) of Module 3,
the interfaces, generics, collections, LINQ, and asynchronous programming of Module 4, four
different persistence mechanisms in Module 5, reflection and concurrency in Module 6, five
user-interface technologies in Module 7, and finally the professional practices of design,
dependency injection, testing, and refactoring in Module 8. This last module doesn't add one
more technique to the pile: it assembles all the previous pieces into a single, coherent,
deployable application. This first lesson lays out the exact scope of that final project, the
architecture decisions that will be made (and why), and the learning objectives it pursues.
Contents
- What "final project" means in this course
- Architecture choice: API + client versus desktop application
- Pieces already built that the project reuses as-is
- Functional scope of the project
- Module 9 learning objectives
- What "final project" means in this course
A common mistake when thinking about a "final project" is imagining you have to start from
scratch, with a new, ambitious idea that shows off everything learned at once. That's not this
module's approach. BiblioTech already exists: it has a mature domain, several ways of
persisting its data, several user interfaces built throughout Module 7, a decoupled architecture
via ILibraryRepository (Module 8), and a suite of unit tests that verify its behavior. What's
missing is joining those pieces into a single coherent application, making concrete decisions
wherever the course, until now, presented separate alternatives (text, JSON, SQLite, or Entity
Framework for persistence; Windows Forms, WPF, ASP.NET Core, Blazor, or MAUI for the interface).
flowchart TD
subgraph "Modules 1-8: pieces built separately"
D["Domain (Modules 3-4)<br/>LibraryItem, Book, Magazine, Member, Loan"]
P["Persistence (Module 5)<br/>Text, JSON, SQLite, EF Core"]
U["Interfaces (Module 7)<br/>WinForms, WPF, ASP.NET Core, Blazor, MAUI"]
A["Architecture (Module 8)<br/>ILibraryRepository, DI, tests, refactoring"]
end
subgraph "Module 9: final project"
F["Complete BiblioTech<br/>one concrete choice per piece, assembled and deployed"]
end
D --> F
P --> F
U --> F
A --> F
A final project that deliberately reuses the work of the entire course, instead of starting from scratch, also reflects how real software development works: a project is rarely started with no prior code, pattern, or decision at all; it's almost always about assembling and completing already-known pieces in a new, concrete way.
- Architecture choice: API + client versus desktop application
Module 7 showed five different ways to give BiblioTech an interface, each valid depending on context. For this final project, one concrete combination must be chosen, and this lesson recommends the following:
| Combination | Advantages for this project | When to prefer it |
|---|---|---|
| ASP.NET Core Minimal API + Blazor client (or a simple HTTP consumer) (recommended) | Separates the domain from the client over HTTP, is currently the most in-demand combination in the .NET job market, lets several different clients (web, mobile, console) consume the same API without duplicating logic | When the goal is a realistic, distributable architecture with more than one potential client type |
| Windows Forms or WPF as a self-contained desktop application | Simpler to run (a single executable, no server to start), reuses Library directly with no HTTP involved |
When the student's interest lies in classic desktop applications, or deploying a web service is best avoided |
| .NET MAUI as a mobile/cross-platform application | Same domain, native interface on mobile and desktop from a single project | When the student's interest lies specifically in cross-platform mobile development |
This lesson and the four that follow develop the first option — ASP.NET Core Minimal API as
the backend, with a simple client consuming it (a Blazor client, or even a console app using
HttpClient, like the one in Module 5) — as the most modern and professionally relevant
combination today. It's still worth stressing an important point: the desktop or mobile
alternatives are just as valid. If you'd rather build the final project with Windows Forms,
WPF, or MAUI instead of a web API, the rest of this module — requirements, planning, testing, the
quality checklist, even most of the deployment work with dotnet publish — applies exactly the
same way; only the Implementation lesson would change, where instead of an API's Program.cs you
would have the corresponding Form/Window/XAML page, consuming Library directly with
ILibraryRepository injected, exactly as you already saw in the Windows Forms, WPF, and MAUI
lessons of Module 7.
One important design difference from Module 7 is worth explaining right away: the Blazor lesson
injected Library directly as a service inside the Blazor Server process itself, with no HTTP
involved. In this final project, by contrast, Library lives only inside the API, and any
client — including a Blazor client — consumes it exclusively through its HTTP endpoints. This is
a deliberate decision: that way, the same API can serve a Blazor client, a future MAUI app, or any
other consumer at the same time, with none of them needing direct access to the process or the
database.
- Pieces already built that the project reuses as-is
None of the following gets rewritten from scratch; the final project picks it up exactly as it was left:
- Domain (Modules 2-3):
LibraryItem(abstract class),BookandMagazineas its two implementations,Member,LoanwithCalculatePenalty(IPenaltyPolicy). - Interfaces and behavioral patterns (Module 4, Module 8):
ILendable,ISearchable,IPenaltyPolicywithFixedPenaltyandProgressivePenalty(Strategy pattern). - The
Libraryclass (Module 4):Catalog,Members,Loans, theLoanRegisteredevent,LendBookAsync,GetMetadataByIsbnAsync(Module 5, querying an external service by ISBN). ILibraryRepository(Module 8) and its four implementations:TextRepository,JsonRepository,SqliteRepository,EntityFrameworkRepository(withLibraryDbContextfrom Module 5).- The xUnit + Moq test suite (Module 8) covering
Loan.RegisterReturn()andLibrary.LendBookAsync. - The coding standards and the outcome of the refactoring (Module 8): consistent naming,
ManageLoanAsyncalready split intoValidateLoanandRegisterAndPersistLoan.
- Functional scope of the project
BiblioTech's final project must cover, at a minimum, the following capabilities — all of them already built in earlier modules, now exposed in a unified way:
| Capability | Originating module |
|---|---|
| Adding, removing, and searching items in the catalog | Modules 3-4 (Catalog, LINQ) |
| Adding members | Module 3 (Member) |
| Registering a loan | Module 4 (LendBookAsync), Module 8 (separate validation) |
| Registering a return, with late-fee penalty calculation | Module 3 (RegisterReturn), Module 8 (IPenaltyPolicy) |
| Looking up external metadata for a book by ISBN | Module 5 (GetMetadataByIsbnAsync, HttpClient) |
| Persisting the catalog durably | Module 5 (concrete choice: Entity Framework Core, see Lesson 2) |
None of these capabilities is new: the work of this module is to expose them all together, in a coherent way, through a single API, instead of having them scattered across separate examples in different lessons.
- Module 9 learning objectives
By completing this module, you will have:
- Defined concrete functional and non-functional requirements for a real application (Lesson 2).
- Planned the work in small iterations, instead of trying to build everything at once (Lesson 2).
- Assembled a solution with several related .NET projects, registering Module 8's dependencies in a real API's DI container (Lesson 3).
- Expanded the test suite with integration tests, and applied debugging and logging techniques in a realistic context (Lesson 4).
- Published and containerized a .NET application, with different configuration per environment (Lesson 5).
Common Mistakes and Tips
- Wanting to add new functionality "because it would be interesting": this module's goal is to assemble and polish what's already built, not to expand BiblioTech's domain; any new idea can be noted down for "after finishing the course," but it shouldn't delay closing out the project.
- Dismissing the desktop or mobile alternatives as "worse": they aren't; choosing ASP.NET Core
- client in this module responds to current job-market relevance and to the chance to show several different clients consuming the same logic, not to Windows Forms, WPF, or MAUI being inferior options.
- Starting to code before reading Lesson 2 (Requirements and Planning): without a clear list of requirements and a phased plan, it's easy to get lost assembling pieces in the wrong order.
- Tip: before writing a single line of code for this project, briefly re-read 08-03
(
ILibraryRepository), 08-04 (testing), and 08-05 (refactoring); they are, quite literally, the exact starting point of Lesson 3 of this module.
Exercises
-
Without looking at Lesson 2 yet, write your own list of 5 use cases you think BiblioTech's final project should cover, based only on the functional scope in section 4.
-
Explain, in two or three sentences, why Module 8's
ILibraryRepositoryarchitecture makes the choice of "which persistence mechanism to use in production" (section 3) a low-risk decision, easy to change later if needed.
Solutions
A reasonable list (yours may vary in wording, but should cover equivalent ideas): (1) adding a new book or magazine to the catalog; (2) searching for items by title or author; (3) adding a new member; (4) registering a loan for an available item; (5) registering the return of a loan, calculating a penalty if it's late.
Since Library depends only on the ILibraryRepository interface (Module 8) and not on any
concrete implementation, changing the production persistence mechanism — for example, from
SQLite to Entity Framework Core, or the other way around — doesn't require modifying Library
or any endpoint that uses it: it's enough to register a different ILibraryRepository
implementation in the DI container (as seen in 08-03, section 7). The risk of that decision is
thus contained to a single point in the program.
Conclusion
This lesson has presented BiblioTech's final project for what it really is: the culmination of eight modules of work, not a new project. You've seen the chosen architecture (ASP.NET Core Minimal API with a client consuming it over HTTP, making clear that desktop or mobile are equally valid alternatives), which concrete pieces from earlier modules get reused as-is, the exact functional scope the project must cover, and this module's learning objectives. With this overall picture now clear, the next lesson, Requirements and Planning, turns that scope into a concrete list of requirements and a phased work plan — the essential step before writing the project's first line of code.
C# Programming Course
Module 1: Introduction to C#
- Introduction to C#
- Setting Up the Development Environment
- Hello World Program
- Basic Syntax and Structure
- Variables and Data Types
- Arrays and Strings
Module 2: Control Structures
Module 3: Object-Oriented Programming
- Classes and Objects
- Methods
- Constructors and Destructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
- Structs and Records: Value Types and Reference Types
Module 4: Advanced C# Concepts
- Interfaces
- Delegates and Events
- Pattern Matching and Modern C# Features
- Generics
- Collections
- LINQ (Language Integrated Query)
- Asynchronous Programming
Module 5: Working with Data
- File I/O
- Serialization
- Database Connectivity
- Entity Framework
- Working with JSON and Consuming REST APIs
Module 6: Advanced Topics
- Reflection
- Attributes
- Dynamic Programming
- Memory Management and Garbage Collection
- Multithreading and Parallel Programming
Module 7: Building Applications
Module 8: Best Practices and Design Patterns
- Coding Standards and Best Practices
- Design Patterns
- Dependency Injection and Inversion of Control
- Unit Testing
- Code Review and Refactoring
