ASP.NET Core Web API

Controllers & ControllerBase

1 Views Updated 5/4/2026

Controllers & ControllerBase

Controllers are the absolute core of your Web API routing logic. They act as the "air traffic controllers" for incoming HTTP requests. They intercept the raw network data, bind it to C# objects, invoke business logic via dependency injection, and format the results back into HTTP status codes and JSON.

1. Controller vs ControllerBase

If you've previously built ASP.NET MVC applications, your classes inherited from Controller. In Web API, we inherit from ControllerBase.

class : Controller (MVC)

Contains all the logic needed to return UI View() results, interact with Razor pages, and render HTML. Highly bloated for pure data APIs.

class : ControllerBase (Web API)

A lightweight base class specifically optimized for REST APIs. It provides only the helper methods required to return raw data and HTTP status codes (e.g., Ok(), NotFound(), BadRequest()).

2. The [ApiController] Attribute

Placing the [ApiController] attribute at the top of a controller is not strictly required, but it is highly recommended as it activates several essential quality-of-life developer features automatically.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Api.Controllers
{
    [ApiController]  // Extraframework magic starts here
    [Route("api/[controller]")]
    public class EmployeesController : ControllerBase
    {
        // action methods...
    }
}

What exactly does [ApiController] do?

  • Automatic 400 Bad Request: You don't have to write if (!ModelState.IsValid) return BadRequest(); at the top of every method anymore. It automatically validates incoming data annotations and instantly returns a 400 JSON response if validation fails.
  • Automatic Model Binding Inference: It automatically infers where parameters come from. For a POST request, it assumes complex objects come from the [FromBody] without you needing to explicitly type the attribute.
  • Multipart/form-data request inference: Makes handling file uploads easier.
  • ProblemDetails integration: Standardizes error JSON responses according to RFC 7807 specifications.

3. Dependency Injection within Controllers

A controller's only job is handling HTTP semantics. It should never contain complex business logic or EF Core DbContext database queries directly. Instead, it relies entirely on Constructor Dependency Injection.

[ApiController]
[Route("api/v1/billing")]
public class BillingController : ControllerBase
{
    // The controller only knows the interface, not the Implementation!
    private readonly IInvoiceService _invoiceService;
    private readonly ILogger<BillingController> _logger;

    // ASP.NET Core's DI system automatically supplies these instances
    public BillingController(IInvoiceService invoiceService, ILogger<BillingController> logger)
    {
        _invoiceService = invoiceService;
        _logger = logger;
    }

    [HttpPost("generate/{customerId}")]
    public async Task<IActionResult> GenerateInvoice(int customerId)
    {
        _logger.LogInformation($"Begin generating invoice for Client ID {customerId}");
        
        // Delegate heavy lifting to the service layer completely.
        var invoiceDto = await _invoiceService.ComputeMonthlyInvoiceAsync(customerId);
        
        if (invoiceDto == null) {
            return NotFound(new { error = "Customer not found in database." });
        }

        // Return a 200 HTTP Status Code attached to the JSON payload
        return Ok(invoiceDto);
    }
}

4. Interview Mastery

Q: "Why should we use Dependency Injection to pass Service interfaces into a Controller instead of just instantiating them with new InvoiceService()?"

Architect Answer: "Tight coupling and testability. If we use the keyword new inside a controller, that controller is permanently glued to a specific infrastructure implementation. If InvoiceService talks to a SQL Database, our Controller now implicitly requires a physical SQL database to be tested. By passing an interface via Constructor Injection, we invert the dependency. During Unit Testing, we can pass a mock framework (like Moq) FakeInvoiceService into the controller, allowing us to perfectly test the Controller's HTTP logic in isolated memory without touching a single database or network socket."

ASP.NET Core Web API
1. Fundamentals & HTTP
Introduction to ASP.NET Core Web API REST Principles and HTTP Methods Controllers & ControllerBase Routing (Attribute vs Conventional) Action Return Types (IActionResult)
2. Request Handling
Model Binding (FromQuery, FromBody, FromRoute) Dependency Injection (DI) Deep Dive App Settings & The Options Pattern
3. Data Access & Architecture
EF Core Setup in Web API DbContext & Migrations Repository & Unit of Work Pattern Asynchronous Programming (async/await)
4. Data Transfer & Validation
Data Transfer Objects (DTOs) & AutoMapper Model Validation (DataAnnotations) FluentValidation Integration
5. Advanced Concepts
Global Exception Handling Middleware Content Negotiation (JSON vs XML) Pagination & Filtering Advanced Searching & Sorting HATEOAS (Hypermedia) Implementation Output Caching & Response Caching
6. Security & Authorization
Cross-Origin Resource Sharing (CORS) JWT Authentication Setup Access Tokens & Refresh Tokens Workflow Role-Based & Policy-Based Authorization API Key Authentication Rate Limiting & Throttling
7. Documentation & Testing
Swagger & OpenAPI Configuration Customizing API Documentation Unit Testing Controllers (xUnit & Moq) Integration Testing (WebApplicationFactory)
8. Microservices & Deployment
Consuming External APIs (IHttpClientFactory) Health Checks & Diagnostics API Versioning Strategies Deploying APIs (Docker & Azure)