Skip to main content
Published / updated

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.

#RuleHow to prove it
1SchoolId from the tokenSign in as School 1, request School 2's student from Postman — expect 403 or empty, never data
2Soft-delete filterDeactivate a student, confirm they leave every list and report
3Composite uniquenessInsert NCA-2024-0012 for School 2 — must succeed; again for School 1 — must fail
4decimal for moneySum 1,000 payments as double and as decimal, compare
5Absent is NULLSELECT COUNT(*) FROM ExamResult WHERE MarksObtained = 0 AND IsAbsent = 1 → must be 0
6Absent check firstResult card for an absent student shows Absent, not Fail
7Transaction propagationForce the second statement to fail; confirm the payment was not written
8Server-side validationPost a payment of -5000 from Postman
9Server-side authorisationCall 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

TestAsserts
Absent student returns AbsentThe condition order
Marks exactly at the pass mark return PassThe boundary — >= not >
Class average with 5 of 40 absentAbsentees excluded
Class where all are absentNo exception; average 0
Balance with a discountThe arithmetic
Payment above the balance is rejectedThe business rule
Duplicate roll number is rejectedComposite uniqueness
Repository filters by SchoolIdMulti-tenancy
A student with two fee accountsThe 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:

  1. Right-click NexCoding.SchoolPortal.ApiPublish.
  2. Target: Folder. Next, then Finish.
  3. In the publish profile, set Configuration to Release and Target Framework to net9.0.
  4. 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

SettingDevelopmentProduction
Connection stringLocalProduction server, restricted login
JWT keyUser secretsVault or environment variable
Detailed errorsOnOff
CORS originslocalhost:5173The real domain only
Log levelDebugInformation

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

FileContainsTest of it
README.mdWhat it is, screenshots, the stackA stranger understands what it does
ENVIRONMENT.mdTools, versions, verify commandsA clean machine reaches a working setup
RUNNING.mdDatabase → API → frontend, with a verification per stepSomeone runs it without asking you
TROUBLESHOOTING.mdProblems that actually happenedSymptom → cause → fix
CONTRIBUTING.mdBranch names, commit format, workflowA 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

QuestionPrepare
Walk me through one requestThe 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 build both 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
  • /version returns the deployed commit
  • All five documents written
  • Someone else ran the project from RUNNING.md unaided
  • 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.

  1. 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.
  2. Review generated API code for validation. Ask for a fee payment endpoint. Before running it, check four things: does schoolId come from the claim or the request? Is the amount validated? Does it return a DTO or the entity? Is Amount a decimal? Record how many of the four it got right.
  3. 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 wantTake
An ORM alternative to DapperTrack 08 — EF Core
The other frontend frameworkTrack 11 — Angular or Track 12 — React
A second languageTrack 13 — Python and FastAPI
NoSQLTrack 14 — MongoDB
To maintain legacy systemsTrack 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.