Search code examples
c#asp.netasp.net-corerazorasp.net-core-mvc

How to extend an ASP.NET Core MVC project by Razor Pages?


I'm currently trying to extend an existing ASP.NET Core MVC project by a Razor page (since several tutorial videos claim that MVC, API, Razor and Blazor can coexist in the same project - but none of them shows how it's done).

I already figured out I need to extend Startup.cs by

services.AddRazorPages();

and

app.UseEndpoints(endpoints =>
{
    // This was here already
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    // I added this
    endpoints.MapRazorPages();
});

I tried simply adding a razor page "Test" to the Views folder, extending the _Layout.cshtml by

<li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Test">Test</a>
</li>

then extending HomeController by

    public IActionResult Test()
    {
        return View();
    }

However, this causes several issues with breakpoints not being hit, or the ViewData dictionary being null (with the identical code working in a pure Razor Page project), probably since it tries treating the Razor Page as an MVC view or something.

I've also tried adding something like

<li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-page="/Home/Test">Test</a>
</li>

to the layout instead, but this produces an URL like

https://localhost:5001/?page=%2FHome%2FTest

when clicking the navbar item.

I can perfectly have both things in separate VS projects, but isn't there a way to use both of them in a single VS project and a single layout?

If you want to try it out before answering, use the following steps:

  1. Create a new project/solution in Visual Studio 2019
  2. Select "ASP.NET Core Web Application" as project template
  3. Click "Create" and select "Web Application (Model-View-Controller)" as template with default settings
  4. Add Razor Support in Startup.cs
  5. Try to make a simple razor page working in this project

Solution

  • The razor pages does not requires a controller.

    The default directory is /Pages, then by default all pages should be inside Pages directory. If you want to change it you can do it by overriding the configuration in ConfigureServices on startup.

    services.AddRazorPages(c=>c.RootDirectory = "/PagesRootDir");
    

    To create a link to page, you should use asp-page tag. For example, if the page name is Test the physical path (by default) will be Pages\Test. To generate the link, you will need to use:

    <a asp-page="/Test">Test Page</a>
    

    By default the pages won't use the default layout, you can always override it.

    @page
    @model WebApplication1.Pages.TestModel
    @{
        Layout = "_Layout";
    }
    
    <h1>
        Test Page
    </h1>
    

    To remove the layout:

    Layout = null;
    

    If you want to use the "Views\Shared\_Layout" on all the pages, you will need to create a _ViewStart with the following code:

    @{
        Layout = "_Layout";
    }
    

    enter image description here