Skip to main content

Controllers and Routing

Level: Intermediate

ℹ️ What You'll Learn
  • Controller purpose: Organize related endpoints (StudentsController for student endpoints, TeachersController for teacher endpoints)
  • [ApiController] attribute: Auto-validates input, returns 400 Bad Request if validation fails, returns problem details on error
  • ControllerBase: Base class for API controllers (JSON responses, no View support)
  • [Route("api/[controller]")]: Base route for all actions in controller (StudentsController → api/students)
  • [HttpGet]: Handle GET requests (read data, safe, idempotent)
  • [HttpPost]: Handle POST requests (create new resource)
  • HttpPut: Handle PUT requests (update entire resource by ID)
  • HttpDelete: Handle DELETE requests (delete resource by ID)
  • Route parameters: HttpGet captures id from URL path for resource identification
  • Route constraints: Constrain parameters to specific types (int, guid) for validation
  • [FromRoute]: Explicit binding from URL parameter (usually not needed, inferred from parameter name)
  • [FromQuery]: Binding from query string (?className=10A → className parameter)
  • [FromBody]: Binding from request body (POST/PUT with JSON → Student object)
  • API versioning: [Route("api/v1/[controller]")] for version 1, api/v2/[controller] for version 2
  • School Management controller structure: StudentsController, TeachersController, ExamsController, FeesController, AttendanceController
  • Action naming: GetStudents (GET all), GetStudent (GET by ID), CreateStudent (POST), UpdateStudent (PUT), DeleteStudent (DELETE)

Controller Basics

File: Controllers/StudentsController.cs

[ApiController]
[Route("api/[controller]")]
public class StudentsController : ControllerBase
{
// Actions here
}

[ApiController] = automatic model validation, problem details response. [Route("api/[controller]")] = base route /api/students

Route Definition

[HttpGet] // GET /api/students
public async Task<ActionResult<List<Student>>> GetStudents()

[HttpGet("{id}")] // GET /api/students/101
public async Task<ActionResult<Student>> GetStudent(int id)

[HttpPost] // POST /api/students
public async Task<ActionResult<Student>> CreateStudent([FromBody] Student student)

[HttpPut("{id}")] // PUT /api/students/101
public async Task<ActionResult> UpdateStudent(int id, [FromBody] Student student)

[HttpDelete("{id}")] // DELETE /api/students/101
public async Task<ActionResult> DeleteStudent(int id)

Route Constraints

[HttpGet("{id:int}")] // id must be integer
[HttpGet("{id:guid}")] // id must be GUID
[HttpGet("{id:min(1)}")] // id >= 1
[HttpGet("search/{query}")] // exact match

Multiple Controllers

SMS API structure:

// StudentsController
[Route("api/[controller]")]
public class StudentsController : ControllerBase

// ExamsController
[Route("api/[controller]")]
public class ExamsController : ControllerBase

// FeesController
[Route("api/[controller]")]
public class FeesController : ControllerBase

Routes:

  • /api/students
  • /api/exams
  • /api/fees

Custom Routes

[Route("api/student")]
public class StudentController : ControllerBase
{
[HttpGet("active")]
public async Task<ActionResult<List<Student>>> GetActiveStudents()
{
// GET /api/student/active
}

[HttpGet("class/{className}")]
public async Task<ActionResult<List<Student>>> GetByClass(string className)
{
// GET /api/student/class/10-A
}
}

Route Order

Routes evaluated top-to-bottom:

[HttpGet("{id:int}")] // Specific routes first
public async Task<ActionResult<Student>> GetStudent(int id)

[HttpGet("{name}")] // General routes last
public async Task<ActionResult<Student>> GetStudentByName(string name)

Key Takeaways

  • Controller = organize related endpoints
  • Route = URL path
  • Constraints = validate route parameters
  • Attribute routing = flexible, explicit
💡 Routing Tip

Keep routes simple and RESTful. /api/students/{id} not /api/get-student-by-id.

🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Controllers and Routing. Try these prompts:

  • "What's the purpose of [ApiController]?"
  • "How do I use route constraints?"
  • "When should I create new controllers?"
  • "Quiz me on routing"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

nexcoding.in