asp.net-core.net-coreroutesrazor-pages

Why is using custom routes returning a 404 in my Razor Pages application?


I want to support URLs like mydomain.com/userName where userName is the username of the persons page they're trying to get to. I'm getting a 404 after adding @page {"userName"} to the top of the .cshtml page. If I remove the {"userName"}, I no longer get the 404 but the standard OnGetAsync() is called without the parameter from the page. Here's all the code:

In the cshtml.cs

public async Task<IActionResult> OnGetAsync(string userName)
{
    var performer = await DbContext.Users.FirstOrDefaultAsync(u => u.UserName == userName);

    return Page();
}

In the top of the .cshtml

@page "{userName}"

And in the Program.cs

app.Use(async (context, next) =>
{
    var path = context.Request.Path.Value;

    // Check if the requested path is not an existing route and is not the root path
    if (!string.IsNullOrEmpty(path) && path != "/" && !path.Contains("."))
    {
        // Check if the requested path matches an existing endpoint
        var endpointFeature = context.Features.Get<IEndpointFeature>();
        if (endpointFeature?.Endpoint == null)
        {
            // Extract username and check if it exists in the database
            using var scope = app.Services.CreateScope();
            var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            var userName = path.TrimStart('/');

            var performer = await dbContext.Users.FirstOrDefaultAsync(u => u.UserName == userName);

            if (performer != null)
            {
                // Rewrite the path to point to the Performers/Home page and keep the userName as a route value
                context.Request.Path = "/Users/Home";
                context.Request.RouteValues["userName"] = userName;

                await next();
                return; // Avoid calling next twice
            }
        }
    }

    await next();
});

Solution

  • It turned out the entire issue was this line:

    context.Request.RouteValues["userName"] = userName;
    

    I had to change it to

    context.Items["userName"] = userName;