Section 2 of 6

Conventional vs Attribute Routing

🎯 What You'll Learn

  • Conventional routing (template-based)
  • Attribute routing (decorator-based)
  • When to use each approach
  • Combining both routing types
  • Token replacement in routes
  • Best practices

Two Routing Approaches

Feature Conventional Routing Attribute Routing
Definition Centralized route templates Routes defined on controllers/actions
Configuration Program.cs Controller attributes
Flexibility Less flexible More flexible
Best For MVC apps with consistent patterns Web APIs, custom routes

Conventional Routing

Conventional routing defines route templates centrally in Program.cs.

Basic Setup

Program.cs C#
builder.Services.AddControllersWithViews();

var app = builder.Build();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

Route Template Breakdown

Template: {controller=Home}/{action=Index}/{id?} Text
{controller=Home}  → Controller name (default: Home)
{action=Index}     → Action name (default: Index)
{id?}              → Optional ID parameter

URL Matching Examples

URL Matching Text
URL: /
→ Controller: Home, Action: Index

URL: /Products
→ Controller: Products, Action: Index

URL: /Products/Details
→ Controller: Products, Action: Details

URL: /Products/Details/123
→ Controller: Products, Action: Details, id: 123

Multiple Routes

Multiple Conventional Routes C#
// Custom route for blog
app.MapControllerRoute(
    name: "blog",
    pattern: "blog/{year}/{month}/{day}/{slug}",
    defaults: new { controller = "Blog", action = "Post" });

// Default route
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
ℹ️ Route Order Matters

Routes are matched in the order they're registered. More specific routes should come before general routes.

Attribute Routing

Attribute routing defines routes using attributes on controllers and actions.

Controller-Level Routes

Controllers/ProductsController.cs C#
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    // GET /api/products
    [HttpGet]
    public IActionResult GetAll() { }

    // GET /api/products/123
    [HttpGet("{id}")]
    public IActionResult GetById(int id) { }

    // POST /api/products
    [HttpPost]
    public IActionResult Create() { }
}

Token Replacement

[controller] and [action] tokens are replaced with actual names.

Token Replacement C#
[Route("api/[controller]")]  // → api/products
public class ProductsController : ControllerBase
{
    [HttpGet("[action]")]  // → api/products/search
    public IActionResult Search() { }
}

Multiple Routes per Action

Multiple Routes C#
[HttpGet("{id}")]
[HttpGet("by-id/{id}")]  // Alternative route
public IActionResult GetById(int id)
{
    // Accessible via:
    // GET /api/products/123
    // GET /api/products/by-id/123
}

Override Controller Route

Absolute Routes C#
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    // Relative route: /api/products/123
    [HttpGet("{id}")]
    public IActionResult GetById(int id) { }

    // Absolute route (starts with /): /health
    [HttpGet("/health")]
    public IActionResult Health() { }
}
⚠️ Absolute Routes

Routes starting with / or ~/ override the controller route. Use sparingly to avoid confusion.

Combining Both Approaches

You can use both conventional and attribute routing in the same application.

Program.cs C#
// Conventional routing for MVC controllers
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

// Attribute routing for API controllers
app.MapControllers();

Complete InvenTrack Example

API Controller (Attribute Routing)

Controllers/ProductsController.cs C#
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    // GET /api/products
    [HttpGet]
    public IActionResult GetAll()
    {
        return Ok("All products");
    }

    // GET /api/products/123
    [HttpGet("{id:int}")]
    public IActionResult GetById(int id)
    {
        return Ok($"Product {id}");
    }

    // GET /api/products/search?name=laptop
    [HttpGet("search")]
    public IActionResult Search([FromQuery] string name)
    {
        return Ok($"Searching for {name}");
    }

    // GET /api/products/category/electronics
    [HttpGet("category/{categoryName}")]
    public IActionResult GetByCategory(string categoryName)
    {
        return Ok($"Products in {categoryName}");
    }

    // POST /api/products
    [HttpPost]
    public IActionResult Create([FromBody] ProductDto product)
    {
        return Created("/api/products/123", product);
    }

    // PUT /api/products/123
    [HttpPut("{id}")]
    public IActionResult Update(int id, [FromBody] ProductDto product)
    {
        return NoContent();
    }

    // DELETE /api/products/123
    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        return NoContent();
    }
}

MVC Controller (Conventional Routing)

Controllers/HomeController.cs C#
public class HomeController : Controller
{
    // GET /
    public IActionResult Index()
    {
        return View();
    }

    // GET /Home/About
    public IActionResult About()
    {
        return View();
    }
}

When to Use Each

Use Conventional Routing Use Attribute Routing
MVC apps with consistent patterns Web APIs
Simple CRUD operations Custom route requirements
Traditional web applications RESTful APIs
When routes follow conventions When routes need flexibility

Best Practices

  • APIs: Use attribute routing for flexibility
  • MVC apps: Use conventional routing for consistency
  • Token replacement: Use [controller] and [action] for maintainability
  • Route order: Specific routes before general routes
  • Absolute routes: Avoid unless necessary
  • Consistency: Stick to one approach per controller type
  • Versioning: Use routes like api/v1/[controller]
  • Documentation: Comment complex routes

Key Takeaways

  • Conventional routing: Centralized templates in Program.cs
  • Attribute routing: Routes defined on controllers/actions
  • Token replacement: [controller] and [action]
  • Flexibility: Attribute routing is more flexible
  • APIs: Prefer attribute routing
  • MVC: Conventional routing works well
  • Combining: Both can coexist in the same app
  • Route order: Matters for conventional routing
  • Absolute routes: Start with / to override controller route
🎯 Next Steps

You now understand conventional vs attribute routing! In the next section, we'll explore Route Parameters—how to capture data from URLs and use it in your actions.