Section 6 of 6

Areas

đŸŽ¯ What You'll Learn

  • What areas are and why use them
  • Creating area structure
  • Routing with areas
  • Area attribute routing
  • URL generation for areas
  • Best practices

What are Areas?

Areas organize large MVC applications into logical sections, each with its own controllers, views, and models.

Why Use Areas?

  • Organization: Separate admin, customer, and public sections
  • Team collaboration: Different teams work on different areas
  • Modularity: Each area is self-contained
  • Scalability: Manage large applications
Example Areas Text
InvenTrack/
├── Areas/
│   ├── Admin/          ← Admin dashboard
│   │   ├── Controllers/
│   │   ├── Views/
│   │   └── Models/
│   ├── Customer/       ← Customer portal
│   │   ├── Controllers/
│   │   ├── Views/
│   │   └── Models/
│   └── Reports/        ← Reporting section
│       ├── Controllers/
│       ├── Views/
│       └── Models/
└── Controllers/        ← Default (no area)

Creating an Area

1. Create Folder Structure

Folder Structure Text
Areas/
└── Admin/
    ├── Controllers/
    │   └── DashboardController.cs
    ├── Views/
    │   ├── Dashboard/
    │   │   └── Index.cshtml
    │   └── _ViewStart.cshtml
    └── Models/

2. Add [Area] Attribute

Areas/Admin/Controllers/DashboardController.cs C#
[Area("Admin")]
public class DashboardController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

3. Configure Routing

Program.cs C#
app.MapControllerRoute(
    name: "areas",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
â„šī¸ {area:exists}

The {area:exists} constraint ensures the route only matches if the area exists. Area routes should come before default routes.

Routing with Areas

URL Pattern

Area URLs Text
/Admin/Dashboard/Index
 ↓      ↓         ↓
Area   Controller Action

Conventional Routing

Program.cs C#
// Area route (must come first)
app.MapControllerRoute(
    name: "admin",
    pattern: "Admin/{controller=Dashboard}/{action=Index}/{id?}",
    defaults: new { area = "Admin" });

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

Attribute Routing with Areas

Using [Area] Attribute C#
[Area("Admin")]
[Route("admin/[controller]/[action]")]
public class ProductsController : Controller
{
    // GET /admin/products/index
    public IActionResult Index() { }

    // GET /admin/products/create
    public IActionResult Create() { }
}

Using [area] Token

Token Replacement C#
[Area("Admin")]
[Route("[area]/[controller]/[action]")]
public class DashboardController : Controller
{
    // GET /admin/dashboard/index
    public IActionResult Index() { }
}

URL Generation for Areas

Url.Action() with Area

Generate Area URLs C#
// Link to area controller
var url = Url.Action("Index", "Dashboard", new { area = "Admin" });
// → /Admin/Dashboard/Index

// Link to default (no area)
var url = Url.Action("Index", "Home", new { area = "" });
// → /Home/Index

In Razor Views

Views/Shared/_Layout.cshtml HTML
<!-- Link to Admin area -->
<a asp-area="Admin" asp-controller="Dashboard" asp-action="Index">
    Admin Dashboard
</a>

<!-- Link to default (no area) -->
<a asp-area="" asp-controller="Home" asp-action="Index">
    Home
</a>

RedirectToAction() with Area

Redirects C#
// Redirect to area
return RedirectToAction("Index", "Dashboard", new { area = "Admin" });

// Redirect to default
return RedirectToAction("Index", "Home", new { area = "" });

Complete InvenTrack Example

Folder Structure

InvenTrack Areas Text
InvenTrack/
├── Areas/
│   ├── Admin/
│   │   ├── Controllers/
│   │   │   ├── DashboardController.cs
│   │   │   ├── ProductsController.cs
│   │   │   └── UsersController.cs
│   │   └── Views/
│   │       ├── Dashboard/
│   │       │   └── Index.cshtml
│   │       ├── Products/
│   │       │   ├── Index.cshtml
│   │       │   └── Create.cshtml
│   │       └── _ViewStart.cshtml
│   └── Reports/
│       ├── Controllers/
│       │   ├── SalesController.cs
│       │   └── InventoryController.cs
│       └── Views/
└── Controllers/
    └── HomeController.cs

Admin Area Controller

Areas/Admin/Controllers/ProductsController.cs C#
[Area("Admin")]
[Route("[area]/[controller]/[action]")]
[Authorize(Roles = "Admin")]
public class ProductsController : Controller
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    // GET /admin/products/index
    public async Task<IActionResult> Index()
    {
        var products = await _productService.GetAllAsync();
        return View(products);
    }

    // GET /admin/products/create
    public IActionResult Create()
    {
        return View();
    }

    // POST /admin/products/create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(ProductViewModel model)
    {
        if (!ModelState.IsValid)
            return View(model);

        await _productService.CreateAsync(model);
        
        // Redirect to Index in same area
        return RedirectToAction(nameof(Index));
    }
}

Reports Area Controller

Areas/Reports/Controllers/SalesController.cs C#
[Area("Reports")]
[Route("[area]/[controller]/[action]")]
public class SalesController : Controller
{
    // GET /reports/sales/monthly
    public IActionResult Monthly()
    {
        return View();
    }

    // GET /reports/sales/yearly
    public IActionResult Yearly()
    {
        return View();
    }
}

Program.cs Configuration

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

var app = builder.Build();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

// Area routes (must come first)
app.MapControllerRoute(
    name: "areas",
    pattern: "{area:exists}/{controller=Dashboard}/{action=Index}/{id?}");

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

app.Run();

Navigation Menu

Views/Shared/_Layout.cshtml HTML
<nav>
    <!-- Default area -->
    <a asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    
    <!-- Admin area -->
    <a asp-area="Admin" asp-controller="Dashboard" asp-action="Index">
        Admin Dashboard
    </a>
    <a asp-area="Admin" asp-controller="Products" asp-action="Index">
        Manage Products
    </a>
    
    <!-- Reports area -->
    <a asp-area="Reports" asp-controller="Sales" asp-action="Monthly">
        Sales Reports
    </a>
</nav>

Best Practices

  • Logical grouping: Group related functionality (Admin, Reports, etc.)
  • Area routes first: Register area routes before default routes
  • Use [Area] attribute: Always decorate area controllers
  • Consistent naming: Use PascalCase for area names
  • Authorization: Apply area-wide authorization
  • Shared layouts: Each area can have its own layout
  • URL generation: Always specify area in links
  • Empty area: Use area = "" for default

When to Use Areas

Use Areas Don't Use Areas
Large applications Small applications
Multiple logical sections Single-purpose apps
Team collaboration Solo projects
Admin vs public sections Simple CRUD apps
Modular architecture APIs (use versioning instead)

Key Takeaways

  • Areas: Organize large MVC apps into logical sections
  • [Area] attribute: Required on area controllers
  • Folder structure: Areas/[AreaName]/Controllers/Views/Models
  • Routing: {area:exists}/{controller}/{action}
  • URL generation: Include area in route values
  • Area routes first: Register before default routes
  • [area] token: Use in attribute routes
  • Empty area: area = "" for default
  • Use cases: Admin panels, reports, customer portals
🎉 Part VII Complete!

Congratulations! You've completed Part VII: Routing. You now understand:

  • ✅ Endpoint routing architecture
  • ✅ Conventional vs attribute routing
  • ✅ Route parameters (required, optional, catch-all)
  • ✅ Route constraints (int, guid, regex, custom)
  • ✅ URL generation (Url.Action, CreatedAtAction, LinkGenerator)
  • ✅ Areas for organizing large applications

You now have complete control over routing in ASP.NET Core! This knowledge is essential for building well-structured, maintainable applications. Keep up the great work! 🚀