Md Mominul Islam | Software and Data Enginnering | SQL Server, .NET, Power BI, Azure Blog

while(!(succeed=try()));

LinkedIn Portfolio Banner

Latest

Home Top Ad

Responsive Ads Here

Wednesday, August 20, 2025

ASP.NET Core Complete Course: Module 4 – Mastering Routing & URL Handling for Modern Web Development

 

Welcome to Module 4 of our ASP.NET Core Complete Course: Beginner to Advanced Guide for Modern Web Development. In this module, we dive deep into Routing & URL Handling, a critical aspect of building user-friendly and efficient web applications in ASP.NET Core. This comprehensive guide covers Conventional vs. Attribute Routing, Route Constraints & Custom Routes, Query Strings & Parameter Binding, and Endpoint Routing in ASP.NET Core.

This blog post is designed to be SEO-friendly, packed with practical examples, detailed explanations, and real-world scenarios to help you master routing in ASP.NET Core. Whether you're a beginner or an advanced developer, this module will equip you with the skills to create clean, maintainable, and dynamic URLs for your web applications. Let’s get started!


Table of Contents

  1. Introduction to Routing & URL Handling

  2. Conventional vs. Attribute Routing

    • What is Conventional Routing?

    • What is Attribute Routing?

    • Conventional vs. Attribute Routing: Key Differences

    • Example: Implementing Conventional and Attribute Routing

  3. Route Constraints & Custom Routes

    • What are Route Constraints?

    • Creating Custom Routes

    • Example: Applying Route Constraints and Custom Routes

  4. Query Strings & Parameter Binding

    • Understanding Query Strings

    • Parameter Binding in ASP.NET Core

    • Example: Handling Query Strings and Parameter Binding

  5. Endpoint Routing in ASP.NET Core

    • What is Endpoint Routing?

    • How Endpoint Routing Works

    • Example: Configuring Endpoint Routing

  6. Best Practices for Routing in ASP.NET Core

  7. Conclusion

  8. FAQs


Introduction to Routing & URL Handling

Routing in ASP.NET Core is the mechanism that maps incoming HTTP requests to specific code (e.g., controller actions or Razor Pages) and generates URLs for navigation. It’s the backbone of how users interact with your application, ensuring that URLs are clean, meaningful, and easy to understand.

In Module 4, we’ll explore the following key topics:

  • Conventional vs. Attribute Routing: Understand the two primary routing approaches and when to use each.

  • Route Constraints & Custom Routes: Learn how to restrict routes and create custom URL patterns.

  • Query Strings & Parameter Binding: Handle dynamic data in URLs and bind it to action parameters.

  • Endpoint Routing: Discover the modern routing system introduced in ASP.NET Core 2.2.

This blog post is example-driven, with step-by-step guides and real-world scenarios to make routing concepts accessible. By the end, you’ll be able to design flexible and user-friendly URL structures for your ASP.NET Core applications.

Why is this important?

  • Routing: Determines how requests are matched to code, impacting performance and usability.

  • Conventional vs. Attribute Routing: Offers flexibility in defining URL patterns.

  • Route Constraints: Ensures routes are precise and secure.

  • Query Strings & Parameter Binding: Enables dynamic and data-driven URLs.

  • Endpoint Routing: Simplifies routing for MVC, Razor Pages, and APIs in a unified system.

Let’s dive into each topic with detailed explanations and practical examples.


Conventional vs. Attribute Routing

Routing in ASP.NET Core can be defined using two primary approaches: Conventional Routing and Attribute Routing. Each has its strengths and use cases, and understanding their differences is key to building effective web applications.

What is Conventional Routing?

Conventional Routing (also called centralized routing) defines routes globally in the application’s startup configuration, typically in Program.cs (or Startup.cs in older versions). It uses a pattern-based approach to map URLs to controllers and actions.

Key Features

  • Routes are defined in a single place (e.g., Program.cs).

  • Uses route templates with placeholders (e.g., {controller}/{action}/{id?}).

  • Ideal for applications with consistent URL patterns.

Example Conventional Route

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

This route maps URLs like /Home/Index or /Products/Details/1 to the corresponding controller and action.

What is Attribute Routing?

Attribute Routing allows you to define routes directly on controllers and actions using attributes. It provides fine-grained control over URL patterns and is ideal for complex or custom routing scenarios.

Key Features

  • Routes are defined using attributes like [Route], [HttpGet], [HttpPost], etc.

  • Offers more flexibility for custom URLs.

  • Commonly used in APIs and applications with unique URL structures.

Example Attribute Route

[Route("api/products")]
public class ProductsController : Controller
{
    [HttpGet]
    public IActionResult GetAll()
    {
        return Ok();
    }

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        return Ok(id);
    }
}

This defines routes like /api/products and /api/products/1.

Conventional vs. Attribute Routing: Key Differences

Feature

Conventional Routing

Attribute Routing

Definition Location

Centralized in Program.cs

On controllers/actions using attributes

Flexibility

Less flexible, pattern-based

Highly flexible, custom URLs

Use Case

Consistent URL patterns (e.g., MVC apps)

APIs, custom URLs, complex routes

Maintenance

Easier to manage for simple apps

Better for large apps with varied routes

Readability

Routes defined in one place

Routes tied to specific actions

Example: Implementing Conventional and Attribute Routing

Let’s create an MVC application to demonstrate both routing approaches.

Step 1: Create a New MVC Project

dotnet new mvc -o MyRoutingApp
cd MyRoutingApp

Step 2: Configure Conventional RoutingUpdate Program.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

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

app.MapControllerRoute(
    name: "blog",
    pattern: "blog/{year}/{month}/{title}",
    defaults: new { controller = "Blog", action = "Post" });

app.Run();

Step 3: Create a Blog ControllerCreate Controllers/BlogController.cs:

using Microsoft.AspNetCore.Mvc;

namespace MyRoutingApp.Controllers
{
    public class BlogController : Controller
    {
        public IActionResult Post(int year, int month, string title)
        {
            ViewData["Message"] = $"Blog post: {title} from {month}/{year}";
            return View();
        }
    }
}

Create Views/Blog/Post.cshtml:

<h1>Blog Post</h1>
<p>@ViewData["Message"]</p>

Step 4: Add Attribute RoutingCreate Controllers/ProductsController.cs:

using Microsoft.AspNetCore.Mvc;

namespace MyRoutingApp.Controllers
{
    [Route("api/products")]
    public class ProductsController : Controller
    {
        [HttpGet]
        public IActionResult GetAll()
        {
            var products = new[] { "Laptop", "Smartphone" };
            return Ok(products);
        }

        [HttpGet("{id}")]
        public IActionResult GetById(int id)
        {
            return Ok($"Product ID: {id}");
        }
    }
}

Step 5: Run the ApplicationRun the application with dotnet run. Test the following URLs:

  • /Home/Index (Conventional Routing)

  • /blog/2025/08/my-first-post (Conventional Routing)

  • /api/products (Attribute Routing)

  • /api/products/1 (Attribute Routing)

Output:

  • /blog/2025/08/my-first-post:

    Blog Post
    Blog post: my-first-post from 8/2025
  • /api/products: ["Laptop","Smartphone"]

  • /api/products/1: "Product ID: 1"

This example demonstrates how to use both Conventional and Attribute Routing to handle different types of URLs.


Route Constraints & Custom Routes

Route Constraints and Custom Routes allow you to fine-tune URL patterns, ensuring they match specific formats and improving the security and usability of your application.

What are Route Constraints?

Route Constraints restrict the values that a route parameter can accept, such as requiring an id to be an integer or a year to be a four-digit number.

Common Route Constraints

  • {id:int}: Matches an integer.

  • {name:alpha}: Matches alphabetic characters.

  • {year:minlength(4):maxlength(4)}: Matches a four-character string.

  • {price:decimal}: Matches a decimal number.

  • {slug:regex(^[a-z0-9-]+$)}: Matches a lowercase slug with letters, numbers, and hyphens.

Creating Custom Routes

Custom Routes allow you to define unique URL patterns beyond the default {controller}/{action}/{id?} template. They are defined in Program.cs or using Attribute Routing.

Example: Applying Route Constraints and Custom Routes

Let’s enhance the Blog application with route constraints and a custom route.

Step 1: Update Program.cs with Constraints

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

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

app.MapControllerRoute(
    name: "blog",
    pattern: "blog/{year:int:min(2000)}/{month:int:range(1,12)}/{title:regex(^[a-z0-9-]+$)}",
    defaults: new { controller = "Blog", action = "Post" });

app.Run();

Explanation:

  • {year:int:min(2000)}: Ensures year is an integer >= 2000.

  • {month:int:range(1,12)}: Ensures month is an integer between 1 and 12.

  • {title:regex(^[a-z0-9-]+$)}: Ensures title is a lowercase slug.

Step 2: Update BlogController.cs

using Microsoft.AspNetCore.Mvc;

namespace MyRoutingApp.Controllers
{
    public class BlogController : Controller
    {
        public IActionResult Post(int year, int month, string title)
        {
            if (string.IsNullOrEmpty(title))
            {
                return BadRequest("Title is required.");
            }
            ViewData["Message"] = $"Blog post: {title} from {month}/{year}";
            return View();
        }
    }
}

Step 3: Test the RoutesTest the following URLs:

  • /blog/2025/08/my-first-post (Valid)

  • /blog/1999/08/my-first-post (Invalid: year < 2000)

  • /blog/2025/13/my-first-post (Invalid: month > 12)

  • /blog/2025/08/My-First-Post (Invalid: title contains uppercase)

Output for /blog/2025/08/my-first-post:

Blog Post
Blog post: my-first-post from 8/2025

This example shows how to use route constraints to enforce URL formats and create custom routes for specific scenarios.


Query Strings & Parameter Binding

Query Strings and Parameter Binding allow you to pass and process dynamic data in URLs, making your application more interactive.

Understanding Query Strings

Query Strings are key-value pairs appended to a URL after a ? (e.g., /Products/Search?category=electronics&maxPrice=1000). They are used to filter, sort, or provide additional parameters.

Parameter Binding in ASP.NET Core

Parameter Binding maps data from HTTP requests (e.g., query strings, route parameters, form data) to action method parameters. ASP.NET Core supports binding from:

  • Route Parameters: {id} in the route template.

  • Query Strings: ?key=value in the URL.

  • Form Data: POST form submissions.

  • JSON Body: For API requests.

  • Headers, Cookies, etc.: Less common sources.

Binding Attributes

  • [FromQuery]: Binds from query strings.

  • [FromRoute]: Binds from route parameters.

  • [FromBody]: Binds from the request body (e.g., JSON).

  • [FromForm]: Binds from form data.

Example: Handling Query Strings and Parameter Binding

Let’s create a product search feature using query strings and parameter binding.

Step 1: Create a ModelCreate Models/Product.cs:

namespace MyRoutingApp.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }
}

Step 2: Create a ControllerCreate Controllers/ProductsController.cs:

using Microsoft.AspNetCore.Mvc;
using MyRoutingApp.Models;
using System.Collections.Generic;
using System.Linq;

namespace MyRoutingApp.Controllers
{
    public class ProductsController : Controller
    {
        private readonly List<Product> _products = new()
        {
            new Product { Id = 1, Name = "Laptop", Price = 999.99m, Category = "Electronics" },
            new Product { Id = 2, Name = "Smartphone", Price = 499.99m, Category = "Electronics" },
            new Product { Id = 3, Name = "Book", Price = 19.99m, Category = "Books" }
        };

        public IActionResult Search([FromQuery] string category, [FromQuery] decimal? maxPrice)
        {
            var filteredProducts = _products.AsQueryable();

            if (!string.IsNullOrEmpty(category))
            {
                filteredProducts = filteredProducts.Where(p => p.Category == category);
            }

            if (maxPrice.HasValue)
            {
                filteredProducts = filteredProducts.Where(p => p.Price <= maxPrice.Value);
            }

            return View(filteredProducts.ToList());
        }

        [Route("products/{id:int}")]
        public IActionResult Details(int id)
        {
            var product = _products.FirstOrDefault(p => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return View(product);
        }
    }
}

Step 3: Create ViewsCreate Views/Products/Search.cshtml:

@model List<MyRoutingApp.Models.Product>

<h1>Product Search</h1>
<form method="get" asp-action="Search">
    <div class="form-group">
        <label for="category">Category</label>
        <input name="category" class="form-control" />
    </div>
    <div class="form-group">
        <label for="maxPrice">Max Price</label>
        <input name="maxPrice" type="number" step="0.01" class="form-control" />
    </div>
    <button type="submit" class="btn btn-primary">Search</button>
</form>
<ul>
    @foreach (var product in Model)
    {
        <li><a asp-action="Details" asp-route-id="@product.Id">@product.Name</a> - $@product.Price (@product.Category)</li>
    }
</ul>

Create Views/Products/Details.cshtml:

@model MyRoutingApp.Models.Product

<h1>Product Details</h1>
<p>Name: @Model.Name</p>
<p>Price: $@Model.Price</p>
<p>Category: @Model.Category</p>
<a asp-action="Search" class="btn btn-secondary">Back to Search</a>

Step 4: Run the ApplicationRun the application and test:

  • /Products/Search?category=Electronics&maxPrice=500 (Filters electronics under $500)

  • /products/1 (Shows details for product ID 1)

Output for /Products/Search?category=Electronics&maxPrice=500:

Product Search
- Smartphone - $499.99 (Electronics)

This example demonstrates how to use query strings for filtering and route parameters for details, with parameter binding to map data to action parameters.


Endpoint Routing in ASP.NET Core

Endpoint Routing is a unified routing system introduced in ASP.NET Core 2.2, used for MVC, Razor Pages, and APIs. It simplifies routing by providing a single mechanism to map requests to endpoints.

What is Endpoint Routing?

Endpoint Routing decouples routing from the middleware pipeline, allowing ASP.NET Core to support multiple frameworks (MVC, Razor Pages, Blazor) with a consistent routing model. It uses endpoints to represent the destinations of HTTP requests.

Key Features

  • Unified routing for MVC, Razor Pages, and APIs.

  • Configured in Program.cs using app.UseRouting() and app.UseEndpoints().

  • Supports middleware integration for authentication, authorization, etc.

  • Improved performance over traditional routing.

How Endpoint Routing Works

  1. Route Matching: The UseRouting middleware matches the incoming request to an endpoint based on the URL.

  2. Endpoint Execution: The UseEndpoints middleware executes the selected endpoint (e.g., a controller action or Razor Page).

  3. Middleware Integration: Middleware like UseAuthorization can be applied before the endpoint is executed.

Example: Configuring Endpoint Routing

Let’s create an application that uses Endpoint Routing for MVC and Razor Pages.

Step 1: Create a Mixed Project

dotnet new mvc -o MyEndpointApp
cd MyEndpointApp
dotnet add package Microsoft.AspNetCore.Mvc.RazorPages

Step 2: Configure Endpoint RoutingUpdate Program.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

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

app.Run();

Step 3: Create a Razor PageCreate Pages/About.cshtml:

@page
@model AboutModel

<h1>About Us</h1>
<p>@Model.Message</p>

Create Pages/About.cshtml.cs:

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace MyEndpointApp.Pages
{
    public class AboutModel : PageModel
    {
        public string Message { get; set; }

        public void OnGet()
        {
            Message = "This is the About page using Razor Pages.";
        }
    }
}

Step 4: Update the MVC ControllerUpdate Controllers/HomeController.cs:

using Microsoft.AspNetCore.Mvc;

namespace MyEndpointApp.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            ViewData["Message"] = "This is the Home page using MVC.";
            return View();
        }
    }
}

Update Views/Home/Index.cshtml:

<h1>Home Page</h1>
<p>@ViewData["Message"]</p>
<a asp-page="/About">Go to About</a>

Step 5: Run the ApplicationRun the application and test:

  • / (MVC Home page)

  • /About (Razor Page)

Output for /:

Home Page
This is the Home page using MVC.
[Go to About]

Output for /About:

About Us
This is the About page using Razor Pages.

This example shows how Endpoint Routing unifies MVC and Razor Pages, allowing both to coexist in the same application.


Best Practices for Routing in ASP.NET Core

  • Use Attribute Routing for APIs: Attribute Routing is ideal for RESTful APIs due to its flexibility.

  • Apply Route Constraints: Use constraints to enforce URL formats and improve security.

  • Keep URLs Clean: Use meaningful, lowercase, and hyphenated URLs (e.g., /blog/my-first-post).

  • Avoid Overlapping Routes: Ensure routes are unique to prevent ambiguity.

  • Use Query Strings Sparingly: Prefer route parameters for essential data and query strings for optional filters.

  • Leverage Endpoint Routing: Use the modern endpoint routing system for better performance and flexibility.

  • Test Routes: Verify that routes work as expected and handle invalid inputs gracefully.


Conclusion

In Module 4 of our ASP.NET Core Complete Course, we explored the intricacies of Routing & URL Handling in ASP.NET Core. You’ve learned how to:

  • Implement Conventional and Attribute Routing to define URL patterns.

  • Use Route Constraints and Custom Routes to enforce specific URL formats.

  • Handle Query Strings and Parameter Binding for dynamic data.

  • Configure Endpoint Routing to support MVC, Razor Pages, and APIs.

Through practical examples, you’ve built applications that demonstrate these concepts in real-world scenarios. In the next module, we’ll dive into advanced topics like Entity Framework Core, authentication, and API development. Stay tuned!


FAQs

Q1: What is the difference between Conventional and Attribute Routing?

  • Conventional Routing defines routes globally in Program.cs, while Attribute Routing defines routes on controllers and actions using attributes.

Q2: When should I use route constraints?

  • Use route constraints to restrict route parameters (e.g., ensuring id is an integer or year is a valid number) for security and usability.

Q3: How does parameter binding work in ASP.NET Core?

  • Parameter binding maps data from route parameters, query strings, form data, or request bodies to action method parameters.

Q4: What is Endpoint Routing, and why is it important?

  • Endpoint Routing is a unified routing system that supports MVC, Razor Pages, and APIs, improving performance and flexibility.

Q5: Can I combine MVC and Razor Pages in the same project?

  • Yes, Endpoint Routing allows MVC and Razor Pages to coexist, with routes defined for each.

No comments:

Post a Comment

Thanks for your valuable comment...........
Md. Mominul Islam