> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/RicardoAlejandroSantillan/dev-showcase/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing System

> Understanding URL routing, profile routes, and language handling in Dev Showcase

## 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:

```csharp Program.cs:12 theme={null}
app.UseRouting();
```

This enables endpoint routing, which is used to define custom route patterns.

## Root Route Redirect

The root URL (`/`) automatically redirects to the default profile:

```csharp Program.cs:16 theme={null}
app.MapGet("/", context =>
{
    context.Response.Redirect("/dataScience", permanent: false);
    return Task.CompletedTask;
});
```

<Info>
  This ensures that visiting the homepage immediately shows the Data Science profile without requiring users to specify a profile.
</Info>

## Language-Only Routes

When users access a language-specific URL without a profile, they're redirected to the default profile:

```csharp Program.cs:22 theme={null}
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

<CodeGroup>
  ```bash Valid URLs theme={null}
  /es          → Redirects to /es/dataScience
  /en          → Redirects to /en/dataScience
  ```

  ```bash Invalid URLs (404) theme={null}
  /fr          → No route match
  /de          → No route match
  /pt          → No route match
  ```
</CodeGroup>

## Profile Routes with Language

The primary routing pattern supports language-specific profile URLs:

```csharp Program.cs:28 theme={null}
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

<ParamField path="lang" type="string" required>
  Language code - must be "es" or "en"
</ParamField>

<ParamField path="profile" type="string" required>
  Profile identifier - must be one of:

  * `dataScience`
  * `webDev`
  * `dataAnalyst`
  * `DataAnalysis`
</ParamField>

### How It Works

<Steps>
  <Step title="URL matches pattern">
    User navigates to `/en/dataScience`
  </Step>

  <Step title="Constraints validated">
    * `lang` = "en" ✓ (matches regex)
    * `profile` = "dataScience" ✓ (matches regex)
  </Step>

  <Step title="Controller action invoked">
    Routes to `HomeController.Profile("dataScience")`
  </Step>

  <Step title="View rendered">
    Returns the HomePage view with the specified profile
  </Step>
</Steps>

### Examples

<CodeGroup>
  ```bash Spanish URLs theme={null}
  /es/dataScience   → Data Science profile in Spanish
  /es/webDev        → Web Developer profile in Spanish
  /es/dataAnalyst   → Data Analyst profile in Spanish
  ```

  ```bash English URLs theme={null}
  /en/dataScience   → Data Science profile in English
  /en/webDev        → Web Developer profile in English  
  /en/dataAnalyst   → Data Analyst profile in English
  ```
</CodeGroup>

## Profile Routes without Language

For convenience, profiles can be accessed without specifying a language:

```csharp Program.cs:38 theme={null}
app.MapControllerRoute(
    name: "profiles",
    pattern: "{profile}",
    defaults: new { controller = "Home", action = "Profile" },
    constraints: new { profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis)$" });
```

This allows shorter URLs like:

```bash theme={null}
/dataScience    → Uses default/cookie language
/webDev         → Uses default/cookie language
/dataAnalyst    → Uses default/cookie language
```

<Note>
  The language displayed depends on the user's language preference cookie. If no cookie exists, the application defaults to Spanish.
</Note>

## Default MVC Route

A fallback route handles standard MVC convention-based routing:

```csharp Program.cs:44 theme={null}
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       |

<Warning>
  This route is rarely used in the application since most navigation goes through the profile routes.
</Warning>

## Controller Implementation

The `HomeController` validates profiles and renders the appropriate view:

```csharp Controllers/HomeController.cs:12 theme={null}
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

1. **Case-Insensitive Comparison**: Uses `StringComparer.OrdinalIgnoreCase` to handle variations
2. **404 on Invalid**: Returns `NotFound()` if profile doesn't exist
3. **ViewData Storage**: Passes profile name to the view via `ViewData`

<Tip>
  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.
</Tip>

## Route Precedence

Routes are evaluated in the order they're defined:

```mermaid theme={null}
graph TD
    A[Incoming Request] --> B{Root / ?}
    B -->|Yes| C[Redirect to /dataScience]
    B -->|No| D{/lang only?}
    D -->|Yes| E[Redirect to /lang/dataScience]
    D -->|No| F{/lang/profile?}
    F -->|Yes| G[ProfileWithLang Route]
    F -->|No| H{/profile?}
    H -->|Yes| I[Profile Route]
    H -->|No| J[Default MVC Route]
```

<Warning>
  **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.
</Warning>

## Adding New Profiles

To add a new profile route:

<Steps>
  <Step title="Update ValidProfiles HashSet">
    Add the profile name to the controller:

    ```csharp theme={null}
    private static readonly HashSet<string> ValidProfiles = new(StringComparer.OrdinalIgnoreCase)
    {
        "dataScience",
        "webDev",
        "dataAnalyst",
        "DataAnalysis",
        "newProfile"  // Add here
    };
    ```
  </Step>

  <Step title="Update Route Constraints">
    Add to the regex patterns in both route definitions:

    ```csharp theme={null}
    constraints: new
    {
        lang = "^(es|en)$",
        profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis|newProfile)$"
    }
    ```
  </Step>

  <Step title="Add Content to Language Files">
    Add profile-specific content to `en.json` and `es.json`
  </Step>
</Steps>

## Testing Routes

You can test routes using curl or a browser:

<CodeGroup>
  ```bash Test Profile Routes theme={null}
  # With language
  curl -I http://localhost:5000/en/dataScience

  # Without language
  curl -I http://localhost:5000/webDev

  # Root redirect
  curl -I http://localhost:5000/
  ```

  ```bash Test Invalid Routes (expect 404) theme={null}
  curl -I http://localhost:5000/invalidProfile
  curl -I http://localhost:5000/fr/dataScience
  ```
</CodeGroup>

## Route Debugging

Enable route debugging in development to see which routes match:

```csharp Program.cs theme={null}
if (app.Environment.IsDevelopment())
{
    app.Use(async (context, next) =>
    {
        Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
        await next();
    });
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Localization" icon="language" href="/architecture/localization">
    Learn how language switching and multilingual content work
  </Card>

  <Card title="Architecture Overview" icon="sitemap" href="/architecture/overview">
    Return to the architecture overview
  </Card>
</CardGroup>
