Search code examples
c#asp.netrazor

ASP.NET Core Razor Pages Endpoint Routing for all Paths after Page Name in URL


So, I'm adapting an MCV example to a Razor Pages application, and have everything working now except for endpoint routing.

Desired behavior:

All text in the URL after the desired page name will be passed to that page's OnGet action as an input variable.

e.g. HTTP://application.tld/Reports/Static/any/text/that/follows is handle by the Static.cshtml.cs page's OnGet(string viewPath) and passes "any/text/that/follows" as the viewPath input variable

Actual behavior:

It tries to find a page at the full location, /Reports/Static/any/text/that/follows, which doesn't exist, so it returns a 404 error.

Using:

  • Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation Version="5.0.3"
  • Microsoft.AspNetCore.Session Version="2.2.0"
  • Microsoft.EntityFrameworkCore Version="5.0.3"

In the MCV example app startup.cs:

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                //Because everything after "Explorer/" is our path and path contains
                //some slashes and maybe spaces, so we can use "Explorer/{*path}"

                routes.MapRoute(
                    name: "Explorer",
                    template: "Explorer/{*path}",
                    defaults: new { controller = "Explorer", action = "Index" });
            });

then in the controller

            public IActionResult Index(string path)

In the Razor Pages app startup.cs:

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();

                endpoints.MapControllerRoute(
                 name: "static",
                 pattern: "/Reports/Static/{*viewPath}",
                 defaults: new { page = "/Reports/Static", action = "OnGet" });
            });

then in the page

            public IActionResult OnGet(string viewPath)

Suggestions on how to get this working?

TIA :0)


Edit with my final solution, with much thanks to @Sergey, and with a catch-all since the number of segments will be variable:

(1) nothing needed for this in the startup.cs so I removed the "endpoints.MapControllerRoute()" section

(2) keep in the page's cshtml.cs file

            public IActionResult OnGet(string viewPath)

(3) and then add in the page's cshtml file

            @page "{*viewPath}"

Solution

  • If you use razor pages you have to put to the top of your page:

    @page "{any}/{text}/{that}/{follows}"
    //or you can use some nullables
    @page "{any}/{text?}/{that?}/{follows?}"
    ````
    in the code behind the page in the action OnGet or OnGetAsync:
    ````
    public async Tast<IActionResult> OnGetAsync( string any, string text, ....)
    ````