Search code examples
c#razorroutesasp.net-core-8

ASP.NET Core 8 Razor Pages Routing with Parameter conflicting PageModels


I'm working with ASP.NET Core 8.0.8. I have various models that represent different tables in a connected database. I have a Table.cshtml razor page that will take the name of a table as a parameter (see below) and display all the relevant information from the database associated with the provided table, which works great.

Table.cshtml:

@page "/{model}"
@model TableModel

I also have a Form.cshtml razor page that will take the name of a table as a parameter along with a form type (see below) and provides the appropriate option depending on the form type provided.

Form.cshtml:

@page "/{model}/{form}"
@model FormModel

My problem occurs when I try to access other pages in my application such as Login.cshtml or Index.cshtml. If I navigate to /Login for instance, it will load the correct page (Login.cshtml) and page model (LoginModel), but for some reason also calls the table page model (TableModel) which causes some conflicts.

I would like to keep parameters as route data within the URL as there will be many separate search query values later on. And I would like to keep the route templates as documented to keep the URL simpler and more readable for the end user.

Ideally I would like the following routes to work as such:

/ -> Index.cshtml with IndexModel
/Login -> Login.cshtml with LoginModel
/Table1 -> Table.cshtml with TableModel
/Table2 -> Table.cshtml with TableModel
/Table1/Create -> Form.cshtml with FormModel
/Table2/Edit -> Form.cshtml with FormModel
/Error/401 -> Error.cshtml with ErrorModel

Here is my current Program.cs:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddRazorPages(options => {
    options.Conventions.AuthorizeFolder("/Pages").AllowAnonymousToPage("/Pages/Error");
});

var app = builder.Build();

// Production IIS folder
app.UsePathBase("/inventoryDEV");

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) {
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
} else app.UseStatusCodePagesWithRedirects("/Error/{0}");

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

//app.UseAuthentication();
//app.UseAuthorization();

//app.UseSession();

app.MapRazorPages();

app.Run();

I tried explicitly specifying the route template in all pages to no avail.

// Index.cshtml
@page "/"
@model IndexModel

// Login.cshtml
@page "/Login"
@model LoginModel

// Error.cshtml
@page "/Error/{status?}"
@model ErrorModel

I also noticed that sometimes the conflicting routing would break my CSS. For whatever reason it would send the current HTML page as, for instance, table.css.

My table.css file would look like this:

<!DOCTYPE html>
<html lang="en">
    <!-- A literal HTML file instead of CSS -->
</html>

UPDATE: It seems this RenderSection() call in my _Layout.cshtml is causing problems, but I'm not sure why. Removing it solves my issue but I lose the page-specific CSS styling functionality I was using.

<head>
    <title>@ViewData["Title"]</title>
    @RenderSection("Styles", false)
</head>

With the RenderSection call in place, the FormModel gets initialized as it seems the {model} parameter is "Form" and the {form} parameter is "dashboard.css" (which is the name of the CSS file I am sending) for some reason.

// Index.cshtml Styles section
@section Styles {
    <link rel="stylesheet" href="@Href("~/css/dashboard.css")" asp-append-version="true" />
}

Solution

  • Like a previous commenter, I also created a new razor page web app with your specified pages and route templates. In my tests, each routing worked as expected and I was not able to replicate the conflict you face. That said, I would recommend doing the following:

    1. Remove the following line from your Program.cs:
    builder.Services.AddRazorPages(options => {
        options.Conventions.AuthorizeFolder("/Pages").AllowAnonymousToPage("/Pages/Error");
    });
    
    • You already call builder.Services.AddRazorPages();, so this could be causing issues with the routing.
    1. Try deleting your .suo file. This is known to help clear random issues occurring with Visual Studio.
      See Delete Your_Solution_FileName.suo file.

    2. You mention using a RenderSection to call the appropriate CSS file for a specific page and omitting this seems to solve your issue. I would suggest looking more into this as I'm not sure why a CSS file would be causing your routing to break, but less strange things have happened. You could also try:

    • Verifying that each @section Styles correctly references your desired CSS file (make sure the href maps correctly).
    • Putting all your CSS into one file and just have the _Layout.cshtml reference that.
    • Looking into CSS isolation.
    1. Check external factors:
    • Ensure Visual Studio is up-to-date
    • Try to disable any VS extensions
    • Check your project file and make sure everything is as expected
    • Try to update any packages or libraries you reference
    • Try to update Windows
    1. As a last resort you can always recreate your project and verify as you go that the routing is still working as expected. Alternatively, you may find that commenting out certain sections will lead you to the problem area.