Creating SEO-Friendly Routes in ASP.NET Core 8

Search engines love clean, meaningful URLs—and users do too. In ASP.NET Core 8, building SEO-friendly routes is easier than ever with attribute routing, custom route constraints, and slugs.
In this guide, I’ll show you how to structure routes that are not just readable, but also rank-worthy.
🔹 Why Clean Routing Matters
✅ Easier for users to understand and share
✅ Boosts keyword relevance in URLs
✅ Improves indexing by search engines
Poor routing is often a missed SEO opportunity. Clean, predictable URLs can improve visibility—especially for content-heavy sites.
1. Use Attribute Routing for Precision
ASP.NET Core supports attribute routing, allowing full control over route structure:
[Route("products/{category}/{id}-{slug}")]
public IActionResult Details(string category, int id, string slug)
{
return View();
}
Resulting URL:
/products/electronics/123-smartphone
✅ Includes keywords
✅ Retains category structure
✅ Uses hyphenated slugs for readability
2. Create Slugs from Titles
Generate URL-safe slugs from titles:
public static class SlugHelper
{
public static string GenerateSlug(string input)
{
return input.ToLower()
.Replace(" ", "-")
.Replace(".", "")
.Replace(",", "");
}
}
string slug = SlugHelper.GenerateSlug("Smartphone Case, Black Edition");
Result: smartphone-case-black-edition
3. Apply Route Constraints
Add constraints for better structure and to prevent bad URLs:
[Route("products/{id:int}/{slug:regex(^[a-z0-9-]+$)}")]
public IActionResult ProductDetails(int id, string slug) => View();
✅ Ensures id
is an integer
✅ Ensures slug
uses only safe characters
4. Build Consistent Global Patterns
In Program.cs
, define default route patterns:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}/{slug?}");
This gives flexibility while preserving URL structure across your app.
5. Add Canonical URLs to Razor Pages
Avoid duplicate content penalties by declaring the canonical version of a page:
<link rel="canonical" href="@Url.Action("Details", "Products", new { id = Model.Id, slug = Model.Slug }, Request.Scheme)" />
6. Handle Redirects When Slugs Change
Use a simple middleware to redirect legacy slugs to updated ones:
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Contains("old-slug"))
{
context.Response.Redirect("/new-slug", permanent: true);
return;
}
await next();
});
✅ Sends a 301 status
✅ Preserves SEO juice
7. Catch and Customize 404s
Graceful 404s help reduce bounce rates:
app.UseStatusCodePagesWithReExecute("/Error/NotFound");
And in ErrorController
:
[Route("Error/NotFound")]
public IActionResult NotFoundPage() => View();
8. Bonus: Dynamic URL Generation
Use helpers like Url.Action
to ensure generated links stay consistent and SEO-friendly:
<a href="@Url.Action("Details", "Products", new { id = product.Id, slug = product.Slug })">View Product</a>
Ready to Implement?
These best practices are built into my DevStack routing layer by default.
You don’t need to start from scratch—I’ve already built the tooling.
- Review my tech experience
- Explore the DevStack platform
- Learn how my business background adds practical value
- And if you’re ready, see pricing
I specialize in scalable, SEO-ready platforms built for growth.
Let’s talk about how clean routing can power your content, products, or app.
Contact me to get started or request access.