ASP.NET Core Web API

Routing (Attribute vs Conventional)

1 Views Updated 5/4/2026

Routing (Attribute vs Conventional)

Routing is how ASP.NET Core matches incoming URLs (like GET /api/users/42) to the exact C# code (Controller and Action Method) that should process the request. Understanding how to structure your routes is crucial for building a predictable, REST-compliant API.

1. Conventional Routing vs Attribute Routing

Conventional Routing (MVC)

Defined globally in Program.cs (e.g., pattern: "{controller}/{action}/{id?}"). Primarily used in traditional MVC UI applications. Anti-Pattern for Web APIs.

Attribute Routing (Web API)

Defined locally using C# Attributes directly above the controllers and action methods. This is the industry standard for Web APIs because it provides fine-grained, explicit control over HTTP semantics.

2. Applying Attribute Constraints

Attribute Routing empowers you to strongly type your URL routes using constraints. If a client sends string data to an endpoint expecting an integer, the route rejects the request instantly with a 404 Not Found before your code even executes.

[ApiController]
// [controller] is a token. It automatically outputs "api/products" 
// by stripping the word "Controller" from the class name.
[Route("api/[controller]")] 
public class ProductsController : ControllerBase
{
    // 1. Basic Route: Matches GET /api/products
    [HttpGet]
    public IActionResult GetAll() { ... }

    // 2. Route Parameter: Matches GET /api/products/42
    // Added a Route Constraint ":int" - enforces the ID MUST be an integer.
    // Added ":min(1)" - enforces ID cannot be 0 or negative.
    [HttpGet("{id:int:min(1)}")]
    public IActionResult GetById(int id) 
    { 
        return Ok($"Found product {id}");
    }

    // 3. Optional Parameters & Defaults: Matches GET /api/products/category/books?page=1
    // A "?" makes a parameter optional, but setting a default value is better.
    [HttpGet("category/{categoryName=General}")]
    public IActionResult GetByCategory(string categoryName) { ... }
}

3. Handling Ambiguous Routes

The most common startup crash in ASP.NET Core APIs is an AmbiguousMatchException. This occurs when two methods try to listen to the exact same URL and HTTP Verb pattern.

// ❌ BAD: DANGEROUS CODE THAT CRASHES APP ON START
[HttpGet]
public IActionResult GetActiveUsers() { ... }

[HttpGet]
public IActionResult GetInactiveUsers() { ... }
// Both methods match "GET /api/users". The framework panics.

// ✅ GOOD: DIVERGING THE PATHS
[HttpGet("active")]   // Matches GET /api/users/active
public IActionResult GetActiveUsers() { ... }

[HttpGet("inactive")] // Matches GET /api/users/inactive
public IActionResult GetInactiveUsers() { ... }

4. Naming Your Routes for Resource Generation

When you create a robust API, you often need to generate a URL pointing to a newly created resource. To do this, you must explicitly Name your routes using the Name = "" parameter.

[HttpPost]
public IActionResult CreateProduct(ProductDto dto)
{
    var newProduct = _db.SaveToDatabase(dto);

    // Creates a 201 Created HTTP Response, AND generates a "Location" header URL
    // pointing back to the "GetProductById" action.
    return CreatedAtRoute("GetProductById", new { id = newProduct.Id }, newProduct);
}

// We explicitly named this route so the POST method above can find it globally
[HttpGet("{id}", Name = "GetProductById")]
public IActionResult GetProduct(int id) { ... }

5. Interview Mastery

Q: "Why is Attribute Routing heavily preferred over Conventional Routing when building RESTful APIs in ASP.NET Core?"

Architect Answer: "RESTful principles dictate that URLs should represent *Resources*, not internal code structures. Conventional Routing forces the URL to mirror the specific Controller and Action method name (e.g., /api/Users/GetActiveUsers). This violates REST standards because 'GetActiveUsers' is an action verb. Attribute routing completely decouples the URL structure from the C# method names. We can name our method GetActiveUsers internally for C# readability, but use [HttpGet('active')] above it, making the resulting URL a clean GET /api/users/active. Furthermore, Attribute Routing natively integrates HTTP verb constraints (GET, POST, PUT), which is foundational to API design."

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)