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

  1. What "final project" means in this course
  2. Architecture choice: API + client versus desktop application
  3. Pieces already built that the project reuses as-is
  4. Functional scope of the project
  5. Module 9 learning objectives

  1. 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.

  1. 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.

  1. 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), Book and Magazine as its two implementations, Member, Loan with CalculatePenalty(IPenaltyPolicy).
  • Interfaces and behavioral patterns (Module 4, Module 8): ILendable, ISearchable, IPenaltyPolicy with FixedPenalty and ProgressivePenalty (Strategy pattern).
  • The Library class (Module 4): Catalog, Members, Loans, the LoanRegistered event, LendBookAsync, GetMetadataByIsbnAsync (Module 5, querying an external service by ISBN).
  • ILibraryRepository (Module 8) and its four implementations: TextRepository, JsonRepository, SqliteRepository, EntityFrameworkRepository (with LibraryDbContext from Module 5).
  • The xUnit + Moq test suite (Module 8) covering Loan.RegisterReturn() and Library.LendBookAsync.
  • The coding standards and the outcome of the refactoring (Module 8): consistent naming, ManageLoanAsync already split into ValidateLoan and RegisterAndPersistLoan.

  1. 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.

  1. 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

  1. 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.

  2. Explain, in two or three sentences, why Module 8's ILibraryRepository architecture 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.

© Copyright 2026. All rights reserved