Test, Deploy, and Explain
Before you start
You need: stage 9 — a working application to verify, deploy and explain.
Time: a week. Verification and the write-up take longer than people expect, and they are what an interviewer asks about.
Learning objective
Verify the project against every rule, produce a deployable build, and explain the whole application in an interview.
Topics
- Verifying the nine rules
- Test coverage that matters
- The deployment build
- Configuration and secrets
- Documentation a stranger can follow
- Explaining the application
- The questions you will be asked
- Where to go next
What this stage covers
The project works. This stage is about proving it works and being able to talk about it.
Most freshers finish a project and stop. The ones who get offers can trace one request through five layers out loud, name a bug they found and how, and say why they chose Dapper over EF Core.
Verifying the rules
Every one of these produces a wrong result with no error message. Test each deliberately and record the evidence.
| # | Rule | How to prove it |
|---|---|---|
| 1 | SchoolId from the token | Sign in as School 1, request School 2's student from Postman — expect 403 or empty, never data |
| 2 | Soft-delete filter | Deactivate a student, confirm they leave every list and report |
| 3 | Composite uniqueness | Insert NCA-2024-0012 for School 2 — must succeed; again for School 1 — must fail |
| 4 | decimal for money | Sum 1,000 payments as double and as decimal, compare |
| 5 | Absent is NULL | SELECT COUNT(*) FROM ExamResult WHERE MarksObtained = 0 AND IsAbsent = 1 → must be 0 |
| 6 | Absent check first | Result card for an absent student shows Absent, not Fail |
| 7 | Transaction propagation | Force the second statement to fail; confirm the payment was not written |
| 8 | Server-side validation | Post a payment of -5000 from Postman |
| 9 | Server-side authorisation | Call an Admin endpoint with a Teacher token |
Screenshot each result. These nine pieces of evidence are what separate a project that works from a project you can defend.
Rule 5's query is the one to run last, because absent-as-zero is the failure most likely to have crept in through a seed script or a generated import.
Tests that matter
| Test | Asserts |
|---|---|
Absent student returns Absent | The condition order |
Marks exactly at the pass mark return Pass | The boundary — >= not > |
| Class average with 5 of 40 absent | Absentees excluded |
| Class where all are absent | No exception; average 0 |
| Balance with a discount | The arithmetic |
| Payment above the balance is rejected | The business rule |
| Duplicate roll number is rejected | Composite uniqueness |
Repository filters by SchoolId | Multi-tenancy |
| A student with two fee accounts | The receipt bug from stage 8 |
Verify each fails without its fix. Comment out the implementation, run, watch it fail, restore. A test that passes either way tests nothing, and generated tests contain those more often than hand-written ones.
Nine focused tests beat sixty that assert the happy path.
The deployment build
Publish the API from Visual Studio:
- Right-click NexCoding.SchoolPortal.Api → Publish.
- Target: Folder. Next, then Finish.
- In the publish profile, set Configuration to Release and Target Framework to
net9.0. - Click Publish. The output folder is shown at the top of the summary.
Configuration must be Release, not Debug. A Debug build carries debugging symbols and skips optimisations, and Visual Studio defaults the profile to whatever you last built.
Build the frontend from a terminal in the web project folder — npm has no Visual Studio equivalent:
npm ci
npm run build
npm ci, not npm install. It installs exactly what the lock file specifies, so the build is reproducible.
One build, promoted through environments. Do not rebuild for production — then the thing tested is not the thing shipped.
1. All tests pass
2. Back up the database
3. Apply migrations
4. Deploy the API
5. Deploy the frontend
6. Smoke test
7. Monitor
Migrations before the application. New code expecting a new column fails without it.
Smoke test:
[ ] Sign in as an office administrator
[ ] Student list loads, filtered to the right school
[ ] Search a known roll number
[ ] Open a fee summary; the balance is correct
[ ] Print a receipt; the watermark appears
[ ] Open a class report; absentees show as Absent
Configuration and secrets
| Setting | Development | Production |
|---|---|---|
| Connection string | Local | Production server, restricted login |
| JWT key | User secrets | Vault or environment variable |
| Detailed errors | On | Off |
| CORS origins | localhost:5173 | The real domain only |
| Log level | Debug | Information |
The developer exception page must be off in production. It exposes stack traces, file paths and often the connection string.
git log -p | grep -i "password\|connectionstring\|apikey"
Must return nothing. A committed secret stays in history — deleting it later does not remove it, and the only real fix is rotating the credential.
Add a /version endpoint so "what is deployed?" is never a guess:
{ "version": "1.0.0", "commit": "a3f9c1d", "environment": "Production" }
Documentation
| File | Contains | Test of it |
|---|---|---|
README.md | What it is, screenshots, the stack | A stranger understands what it does |
ENVIRONMENT.md | Tools, versions, verify commands | A clean machine reaches a working setup |
RUNNING.md | Database → API → frontend, with a verification per step | Someone runs it without asking you |
TROUBLESHOOTING.md | Problems that actually happened | Symptom → cause → fix |
CONTRIBUTING.md | Branch names, commit format, workflow | A new contributor knows what to do |
The test for RUNNING.md is a person, not a checklist. Hand it to someone with a clean machine and watch. Every question they ask is a missing line.
Explaining the application
Prepare a five-minute walkthrough. Not a feature tour — an architecture explanation.
1. The problem The office spent minutes finding one student; fee
receipts were handwritten and did not reconcile.
2. The stack React, ASP.NET Core Web API, Dapper, SQL Server.
Dapper rather than EF Core, so I could see and tune
the SQL — this is a reporting-heavy application.
3. One request A clerk clicks Print. The browser sends GET with the
JWT. The controller reads schoolId from the claim —
never from the request — and calls FeeService.
The service calls FeeRepository, which runs a stored
procedure joining FeePayment, FeeAccount and Student,
filtered by SchoolId. The service builds a DTO with
only what the clerk may see. The component renders it
with a print stylesheet.
4. A hard decision Absent exam results are stored as NULL, not 0. Zero
would drag every class average down by roughly 12%
with no error anywhere. The absent check therefore
comes first in every grading chain.
5. A bug I found Receipts showed a zero balance for one student. I
traced it: the frontend rendered what the API sent,
the API's SQL was running, and the database had two
fee accounts for that student — he had repeated a
year. FirstOrDefault picked the older one. I filtered
by academic year and added a test for it.
6. What I would add Pagination, an audit trail on fee changes, and a
second-approval step on discounts.
Point 5 is the one interviewers remember. It shows a method, not luck — four boundary checks, a specific cause, a minimal fix, a test.
Point 6 shows judgement. Knowing what is missing is a stronger signal than claiming nothing is.
The questions you will be asked
| Question | Prepare |
|---|---|
| Walk me through one request | The five-layer trace, out loud |
| Why Dapper and not EF Core? | Control over SQL; reporting-heavy; you learned SQL first |
| How is multi-tenancy enforced? | The claim, and the WHERE clause in every query |
| How do you stop SQL injection? | Parameters everywhere; demonstrate one |
| What happens if two payments arrive at once? | Database-side increment inside a transaction |
Why is money decimal? | Show the double sum that is wrong by paise |
| How did you test it? | The nine focused tests, each failing without its fix |
| What was the hardest bug? | The receipt trace |
| What would you do differently? | An honest answer, with a reason |
"I don't know, but here is how I would find out" is a good answer. Bluffing is not, and it is obvious.
Final verification
- All nine rules proved, with evidence recorded
- Every test fails when its fix is removed
- The Visual Studio Publish profile and
npm run buildboth succeed - The built frontend runs against the API
- No secret anywhere in Git history
- Developer exception page off in Release
- CORS restricted to the real origin
-
/versionreturns the deployed commit - All five documents written
- Someone else ran the project from
RUNNING.mdunaided - You can trace one request through five layers without notes
- You can name a bug you found and how you found it
AI practice
Three AI exercises from the guided path syllabus. Do each after the project is verified, and apply Track 18's discipline — every answer is a hypothesis until you have run it.
- Ask AI for an approach, not a full application. Describe one feature you have not built yet — an audit trail on fee changes — and ask for the approach and its trade-offs, with no code. Then implement it yourself and compare what you chose.
- Review generated API code for validation. Ask for a fee payment endpoint. Before running it, check four things: does
schoolIdcome from the claim or the request? Is the amount validated? Does it return a DTO or the entity? IsAmountadecimal? Record how many of the four it got right. - Explain every changed file before committing. Take your largest pull request and write one sentence per changed file on what it does and why. Any file you cannot explain does not belong in the commit — remove it or understand it.
Exercise 2 measures the rate at which your assistant needs telling. Whatever rate you find is the rate you must catch in review, permanently.
Track 18 — Reviewing AI-generated code — has the full checklist.
Track completion criteria
You can understand, develop, test and explain a realistic beginner-to-intermediate full-stack application.
Specifically, you can:
- Describe how a software team works and where a fresher fits
- Turn a business request into a story with testable acceptance criteria
- Write, debug and explain structured C# with practical OOP, collections and LINQ
- Design a normalised multi-tenant SQL Server schema with constraints and procedures
- Connect C# to SQL Server safely with Dapper, parameters and transactions
- Build a validated, secured ASP.NET Core Web API with correct status codes
- Build a responsive component-based frontend that handles every failure state
- Work on branches with pull requests, and recover from Git mistakes
- Trace a failure across all five layers to its cause
- Use AI to accelerate work without losing ownership of it
- Enforce the nine rules that fail silently — tenancy, soft delete, composite uniqueness,
decimal, absent-as-null, absent-check-first, transaction propagation, server-side validation, server-side authorisation - Produce a deployable build and documentation a stranger can follow
- Explain your architecture, one request, a hard decision and a bug you found
Where to go next
| If you want | Take |
|---|---|
| An ORM alternative to Dapper | Track 08 — EF Core |
| The other frontend framework | Track 11 — Angular or Track 12 — React |
| A second language | Track 13 — Python and FastAPI |
| NoSQL | Track 14 — MongoDB |
| To maintain legacy systems | Track 04 — VB.NET, Track 05 — Web Forms |
The syllabus recommends Track 08 — Entity Framework Core or a deeper pass through Track 10 — ASP.NET Core Development after this path.
Return to the Track 01 overview.