Legacy Student Records Module
Before you start
You need: all of Articles 01–07, and the SQL basics noted in Article 07.
In Visual Studio: open the supplied solution and build it before changing anything. If it will not load, Article 01 lists the usual causes.
Time: 5–8 hours. The diagnosis write-up is half the exercise.
Goal
Demonstrate that you can take an existing Web Forms page, diagnose defects across the lifecycle, state, and data layers, and fix them without redesigning the page or introducing a regression.
Assignment
You are given a student records page in an existing Web Forms application for NexCoding Academy. It lists students in a GridView with a search box and a class dropdown, and allows editing. Four defects are reported. Produce:
- A page document: file set, master page, control inventory, event wiring, lifecycle notes, and the call chain to the database.
- A reproduction for each defect — steps, input, expected, actual.
- A diagnosis naming the responsible line and the lifecycle stage or store involved.
- One controlled change per defect.
- A regression list and how you checked each item.
- Evidence a reviewer can repeat.
The reported defects
Defect A. Typing a name and clicking Search shows all students, unfiltered. The search box still contains the term.
Defect B. The class dropdown resets to "-- All classes --" after every button click.
Defect C. Editing a student whose class was removed from the school's class list throws ArgumentOutOfRangeException before the page renders.
Defect D. Users are logged out and lose their work every morning at the same time. Nobody has been idle.
Worked example: the survey
File set
Students/List.aspx markup, Content inside Site.master
Students/List.aspx.vb code-behind
Students/List.aspx.designer.vb generated
Site.master shared layout, holds the form
Data/StudentData.vb Module — data access
Web.config connection string, sessionState
Control inventory
| Control | Type | Wiring | AutoPostBack |
|---|---|---|---|
txtSearch | TextBox | — | — |
ddlClass | DropDownList | SelectedIndexChanged via Handles | false |
btnSearch | Button | Handles btnSearch.Click | — |
grdStudents | GridView | RowCommand via AddHandler in Page_Init | — |
grdStudents's handler is wired with AddHandler, so searching the code-behind for grdStudents finds only the declaration. This is worth recording in the document — the next person will look for it too.
Call chain
btnSearch_Click
└─ LoadStudents()
└─ StudentData.Search(schoolId, term) ' Module — unqualified call
└─ SqlCommand → usp_SearchStudents
SchoolId comes from Session("SchoolId"), read inside LoadStudents, not passed in.
The code as found
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
LoadClassDropDown()
LoadStudents()
End Sub
Protected Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
LoadStudents(txtSearch.Text)
End Sub
Private Sub LoadStudents(Optional term As String = "")
grdStudents.DataSource = StudentData.Search(CInt(Session("SchoolId")), term)
grdStudents.DataBind()
End Sub
Private Sub LoadClassDropDown()
ddlClass.DataSource = StudentData.GetClassNames(CInt(Session("SchoolId")))
ddlClass.DataTextField = "ClassName"
ddlClass.DataValueField = "ClassName"
ddlClass.Items.Insert(0, New ListItem("-- All classes --", String.Empty))
ddlClass.DataBind()
End Sub
Protected Sub LoadStudentForEdit(student As Student)
txtName.Text = student.Name
ddlEditClass.SelectedValue = student.ClassName
End Sub
<sessionState mode="InProc" timeout="20" />
Worked example: diagnosis
Defect A — search shows everything
Page_Load has no IsPostBack guard. On the Search postback the lifecycle runs:
Page_Load → LoadStudents() with no term → binds ALL students
btnSearch_Click → LoadStudents(term) → binds filtered students
The click handler does run, and it does bind correctly. But LoadClassDropDown in step 1 also re-ran, and depending on control order the second bind is what the user sees — or the first bind's result is what remains after the grid's ViewState is restored. Either way the reported symptom is the same.
Responsible line: Page_Load calling LoadStudents() unguarded.
Defect B — dropdown resets
Same root cause, different symptom. LoadClassDropDown() runs on every postback, and DataBind() clears and rebuilds the items collection, discarding the user's selection.
There is a second, independent bug in the same method: Items.Insert is called before DataBind(). Binding clears the collection, so the placeholder is removed every time. The dropdown has no "-- All classes --" option at all — which nobody reported because the reset masked it.
Responsible lines: the unguarded call in Page_Load, and the Insert before DataBind.
Defect C — ArgumentOutOfRangeException on edit
ddlEditClass.SelectedValue = student.ClassName
SelectedValue throws when the value is not present in the list. A student recorded against a class that has since been removed from GetClassNames has no matching item, so the assignment throws — before render, which is why the page never appears.
This is a data problem surfacing as a code problem. The fix must handle the missing value; deleting the class from those students is a data decision, not a maintenance change.
Responsible line: the direct SelectedValue assignment.
Defect D — everyone logged out each morning
Not idle, all users at once, at a fixed time. That is the IIS application pool recycle, not a session timeout.
<sessionState mode="InProc" timeout="20" />
InProc holds session in the worker process's memory. The default IIS recycle schedule destroys it, and every user's session goes with it.
Responsible line: mode="InProc" combined with the default recycle schedule.
Note carefully: this is a configuration and infrastructure issue, not a page defect. The correct fix — moving to StateServer or SQLServer mode — requires every object stored in session to be serialisable and needs a service or database provisioned. That is a change to raise with your lead, not to make inside a page-fix ticket.
Worked example: the controlled change
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
' Every request — a security check must not be skipped on postbacks
If Session("SchoolId") Is Nothing Then
Response.Redirect("~/Login.aspx", False)
Return
End If
' First request only
If Not IsPostBack Then
LoadClassDropDown()
LoadStudents()
End If
End Sub
Private Sub LoadClassDropDown()
ddlClass.DataSource = StudentData.GetClassNames(CInt(Session("SchoolId")))
ddlClass.DataTextField = "ClassName"
ddlClass.DataValueField = "ClassName"
ddlClass.DataBind()
' After DataBind — binding clears the items collection
ddlClass.Items.Insert(0, New ListItem("-- All classes --", String.Empty))
End Sub
Protected Sub LoadStudentForEdit(student As Student)
txtName.Text = student.Name
Dim item As ListItem = ddlEditClass.Items.FindByValue(student.ClassName)
If item Is Nothing Then
' The class no longer exists — keep it visible rather than losing the value
ddlEditClass.Items.Add(New ListItem(student.ClassName & " (discontinued)",
student.ClassName))
item = ddlEditClass.Items.FindByValue(student.ClassName)
End If
ddlEditClass.ClearSelection()
item.Selected = True
End Sub
What changed, and what deliberately did not:
| Change | Reason |
|---|---|
IsPostBack guard added | Fixes defects A and B |
| Session check left outside the guard | It must run on every request, including postbacks |
Items.Insert moved after DataBind() | Fixes the missing placeholder |
FindByValue replaces SelectedValue = | Fixes defect C |
| Discontinued class added to the list | Preserves the student's actual value instead of silently changing it |
sessionState not changed | Defect D needs infrastructure — raised separately |
StudentData left as a Module | Converting it changes every call site |
AddHandler wiring left as found | Works correctly; changing it is unrelated |
SchoolId still read inside LoadStudents | Real improvement, out of scope for this ticket |
The defect C fix deserves attention. Silently selecting the first item, or leaving the dropdown blank, would let a save quietly rewrite the student's class to something the user never chose. Adding the discontinued value keeps the record accurate and makes the situation visible. A fix that prevents a crash by corrupting data is not a fix.
Worked example: regression check
| What to check | Why |
|---|---|
| Search with a term | The reported case |
| Search with an empty term | Must still return everything |
| Search, then change page | Filter must survive paging |
| Dropdown selection after any postback | Must persist |
| "-- All classes --" present on first load | The masked second bug |
| First load still populates the grid | The IsPostBack guard must not suppress the initial bind |
| Edit a student with a current class | Must still select correctly |
| Edit a student with a discontinued class | Must render, and must keep the original value on save |
| Save after editing a discontinued class | Confirm the value written is unchanged |
| Session expired, then any click | Must redirect to login, not throw |
Other callers of StudentData.GetClassNames | The method is unchanged, but confirm with Find all references |
| Row commands on the grid | The AddHandler wiring must still fire |
The row-command row matters: the IsPostBack guard changes what runs before the command handler, so verify the grid's DataKeys are still populated on postback. They come from ViewState, so they are — but confirming it is the difference between believing and knowing.
Submission template
Page and file set:
Master page and form location:
Control inventory (control, type, wiring, AutoPostBack):
Event wiring notes (anything not found by name search):
Call chain (control → handler → method → SQL):
State stores used (ViewState / Session / query string) and where read:
Defect A — search unfiltered
Reproduction, expected vs actual:
Lifecycle stage responsible:
Responsible line:
Change made:
Defect B — dropdown resets
Reproduction, expected vs actual:
Root cause and the second bug it masked:
Change made:
Defect C — exception on edit
Reproduction, expected vs actual:
Why the data caused a code failure:
Change made, and why not the simpler option:
Defect D — daily logout
Evidence it is a recycle, not a timeout:
Why this was not fixed in this change:
Recommendation raised:
Deliberately not changed (and why):
Regression list and how each was checked:
Evidence (before / after, repeatable steps):
AI practice
Two AI exercises from this track's syllabus. Do both after the module works, and apply Track 18's discipline — every answer is a hypothesis until you have run it.
- Ask AI to explain a lifecycle event sequence. Ask what runs, in order, when a
GridViewrow-edit postback occurs, and whereViewStateis restored relative toPage_Load. Then verify it by adding a trace line to each handler and reading the actual order. TheIsPostBackcheck and the position ofViewStaterestoration are the two most commonly described wrongly. - Review generated Web Forms code for unsafe SQL. Ask for a
GridViewbound to a student search. Before running it, check whether the query concatenates the search box value into the SQL string. Generated Web Forms code does this often, because most Web Forms examples online predate the parameterised habit — and searching forO'Brienis how you find it.
Exercise 2 is the calibration one. Web Forms is precisely where a model's training data is oldest and least safe.
Track 18 — Reviewing AI-generated code — has the full checklist.
Self-assessment
Your submission is complete when someone who has never opened this application can find the page from your document, reproduce all four defects, understand which lifecycle stage or state store caused each, repeat your verification, and see which improvements you consciously left out.
Three specific tests of quality:
- Did you separate the infrastructure issue from the page defects? Defect D shares a symptom with a code bug but is neither diagnosed nor fixed the same way. Treating all four identically is the mistake this assignment is built to expose.
- Did your defect C fix preserve the data? A fix that stops the exception by silently changing the student's class is worse than the crash.
- Can a reviewer tell from the diff which line fixes which defect? If not, the change is doing too much at once.
Track completion criteria
You can understand a common Web Forms application structure, maintain a database-backed page, and debug state and event problems.
Specifically, you can:
- State the lifecycle order and explain why
Page_Loadruns before every click handler - Diagnose an event that does not fire, across all four causes
- Choose between ViewState, Session, query string, and the database for a given value
- Tell a session timeout from an app pool recycle by its timing pattern
- Build a form whose validation holds with scripting disabled
- Bind a
GridViewwhose row commands cannot reach another tenant's data - Separate a page defect from an infrastructure problem, and route each correctly
The syllabus recommends Track 10 — ASP.NET Core Development next — the modern framework that replaced Web Forms. If you have not yet done Track 06 — SQL Server and Track 07 — ADO.NET & Dapper, take those first.