1
votes

In the default Razor Pages project template, part of the code in Startup.cs that enables Razor Pages is the call to MapRazorPages() in the endpoint configuration section of Configure():

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

The necessity of this call is confirmed in the excellent Introduction to Razor Pages in ASP.NET Core article by Rick Anderson and Ryan Nowak.

While Blazor is a different UI technology, Blazor projects are also able to expose Razor Pages endpoints. For example, a Blazor project that includes ASP.NET Identity authentication exposes the Login and LogOut pages as Razor Pages.

However, the endpoint initialization in a Blazor project that exposes Razor Pages does not appear to involve a call to MapRazorPages(). If you create a new project using the default Blazor template with individual user account authentication, then scaffold in all of the Razor Pages used by ASP.NET Identity, the endpoint initialization winds up looking like this:

app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });

The resultant application is able to properly route requests to Razor Pages endpoints like Login.cshtml and LogOut.cshtml. How is this possible without the call to MapRazorPages()?

1

1 Answers

2
votes

First have a look at the following code snippets (Take note of the highlighted lines in both)

Reference MapRazorPages

/// <summary>
/// Adds endpoints for Razor Pages to the <see cref="IEndpointRouteBuilder"/>.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
/// <returns>An <see cref="PageActionEndpointConventionBuilder"/> for endpoints associated with Razor Pages.</returns>
public static PageActionEndpointConventionBuilder MapRazorPages(this IEndpointRouteBuilder endpoints)
{
    if (endpoints == null)
    {
        throw new ArgumentNullException(nameof(endpoints));
    }

    EnsureRazorPagesServices(endpoints); //<-- NOTE THIS

    return GetOrCreateDataSource(endpoints).DefaultBuilder;
}

Reference MapFallbackToPage

public static IEndpointConventionBuilder MapFallbackToPage(this IEndpointRouteBuilder endpoints, string page)
{
    if (endpoints == null)
    {
        throw new ArgumentNullException(nameof(endpoints));
    }

    if (page == null)
    {
        throw new ArgumentNullException(nameof(page));
    }

    PageConventionCollection.EnsureValidPageName(page, nameof(page));

    EnsureRazorPagesServices(endpoints); //<-- NOTE THIS

    // Called for side-effect to make sure that the data source is registered.
    GetOrCreateDataSource(endpoints).CreateInertEndpoints = true;

    // Maps a fallback endpoint with an empty delegate. This is OK because
    // we don't expect the delegate to run.
    var builder = endpoints.MapFallback(context => Task.CompletedTask);
    builder.Add(b =>
    {
        // MVC registers a policy that looks for this metadata.
        b.Metadata.Add(CreateDynamicPageMetadata(page, area: null));
    });
    return builder;
}

They both make calls to the core function that configures features to handle razor page requests.