Overview
Dev Showcase uses ASP.NET Core’s routing system to map incoming URLs to controller actions. The application has a sophisticated routing configuration that handles profile-specific routes and multilingual URLs.
Route Configuration
All routes are configured in Program.cs using the routing middleware:
This enables endpoint routing, which is used to define custom route patterns.
Root Route Redirect
The root URL (/) automatically redirects to the default profile:
app . MapGet ( "/" , context =>
{
context . Response . Redirect ( "/dataScience" , permanent : false );
return Task . CompletedTask ;
});
This ensures that visiting the homepage immediately shows the Data Science profile without requiring users to specify a profile.
Language-Only Routes
When users access a language-specific URL without a profile, they’re redirected to the default profile:
app . MapGet ( "/{lang:regex(^(es|en)$)}" , ( string lang , HttpContext context ) =>
{
context . Response . Redirect ( $"/ { lang } /dataScience" , permanent : false );
return Task . CompletedTask ;
});
Route Constraints
This route uses a regex constraint to ensure the lang parameter only matches valid language codes:
{lang:regex(^(es|en)$)} - Only accepts “es” (Spanish) or “en” (English)
Invalid values like /fr or /de will not match this route
Valid URLs
Invalid URLs (404)
/es → Redirects to /es/dataScience
/en → Redirects to /en/dataScience
Profile Routes with Language
The primary routing pattern supports language-specific profile URLs:
app . MapControllerRoute (
name : "profilesWithLang" ,
pattern : "{lang}/{profile}" ,
defaults : new { controller = "Home" , action = "Profile" },
constraints : new
{
lang = "^(es|en)$" ,
profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis)$"
});
Route Parameters
Language code - must be “es” or “en”
Profile identifier - must be one of:
dataScience
webDev
dataAnalyst
DataAnalysis
How It Works
URL matches pattern
User navigates to /en/dataScience
Constraints validated
lang = “en” ✓ (matches regex)
profile = “dataScience” ✓ (matches regex)
Controller action invoked
Routes to HomeController.Profile("dataScience")
View rendered
Returns the HomePage view with the specified profile
Examples
/es/dataScience → Data Science profile in Spanish
/es/webDev → Web Developer profile in Spanish
/es/dataAnalyst → Data Analyst profile in Spanish
Profile Routes without Language
For convenience, profiles can be accessed without specifying a language:
app . MapControllerRoute (
name : "profiles" ,
pattern : "{profile}" ,
defaults : new { controller = "Home" , action = "Profile" },
constraints : new { profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis)$" });
This allows shorter URLs like:
/dataScience → Uses default/cookie language
/webDev → Uses default/cookie language
/dataAnalyst → Uses default/cookie language
The language displayed depends on the user’s language preference cookie. If no cookie exists, the application defaults to Spanish.
Default MVC Route
A fallback route handles standard MVC convention-based routing:
app . MapControllerRoute (
name : "default" ,
pattern : "{controller=Home}/{action=HomePage}/{id?}" )
. WithStaticAssets ();
Route Template Breakdown
Segment Description Default {controller=Home}Controller name Home{action=HomePage}Action method HomePage{id?}Optional parameter None
This route is rarely used in the application since most navigation goes through the profile routes.
Controller Implementation
The HomeController validates profiles and renders the appropriate view:
Controllers/HomeController.cs:12
private static readonly HashSet < string > ValidProfiles = new ( StringComparer . OrdinalIgnoreCase )
{
"dataScience" ,
"webDev" ,
"dataAnalyst" ,
"DataAnalysis"
};
public IActionResult Profile ( string profile )
{
if ( ! ValidProfiles . Contains ( profile ))
return NotFound ();
ViewData [ "Profile" ] = profile ;
return View ( "HomePage" );
}
Validation Logic
Case-Insensitive Comparison : Uses StringComparer.OrdinalIgnoreCase to handle variations
404 on Invalid : Returns NotFound() if profile doesn’t exist
ViewData Storage : Passes profile name to the view via ViewData
The same view (HomePage.cshtml) is used for all profiles. JavaScript reads the ViewData["Profile"] value to load the appropriate content from the language JSON files.
Route Precedence
Routes are evaluated in the order they’re defined:
Order matters! More specific routes must be defined before more general ones. If the default route were defined first, it would match before the profile routes could be evaluated.
Adding New Profiles
To add a new profile route:
Update ValidProfiles HashSet
Add the profile name to the controller: private static readonly HashSet < string > ValidProfiles = new ( StringComparer . OrdinalIgnoreCase )
{
"dataScience" ,
"webDev" ,
"dataAnalyst" ,
"DataAnalysis" ,
"newProfile" // Add here
};
Update Route Constraints
Add to the regex patterns in both route definitions: constraints : new
{
lang = "^(es|en)$" ,
profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis|newProfile)$"
}
Add Content to Language Files
Add profile-specific content to en.json and es.json
Testing Routes
You can test routes using curl or a browser:
Test Profile Routes
Test Invalid Routes (expect 404)
# With language
curl -I http://localhost:5000/en/dataScience
# Without language
curl -I http://localhost:5000/webDev
# Root redirect
curl -I http://localhost:5000/
Route Debugging
Enable route debugging in development to see which routes match:
if ( app . Environment . IsDevelopment ())
{
app . Use ( async ( context , next ) =>
{
Console . WriteLine ( $"Request: { context . Request . Method } { context . Request . Path } " );
await next ();
});
}
Next Steps
Localization Learn how language switching and multilingual content work
Architecture Overview Return to the architecture overview