Search code examples
c#asp.net-coreblazorblazor-server-siderazor-components

Add Razor Page Component in MVC


I've added Razor Page Component to my existing MVC application

Pages/Test.razor

@page "/test"

<h1>Hello World!</h1>

@code {
    
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddServerSideBlazor();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
    endpoints.MapBlazorHub();
});

app.Run();

Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - MVCApp</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/MVCApp.styles.css" asp-append-version="true" />
    <base href="/"/>
    <script src="_framework/blazor.server.js"></script>
...

but it doesn't work: I get 404 on /test

enter image description here

What am I missing to make Razor Component's routing work with MVC routing?


Solution

  • You need to install the Microsoft.AspNetCore.Components package and add the _Host.cshtml, App.razor, _Imports.razor files to your MVC project.

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.AspNetCore.Components.Web.Virtualization
    @using Microsoft.JSInterop
    @using Project
    

    _Host.cshtml:

    @page "/"
    @namespace Project.Pages
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @{
        Layout = "_Layout";
    }
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView>
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
    

    Your Endpoints:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    

    Test Result:

    enter image description here

    If you want to use the UI in Blazor, you can also copy MainLayout.razor from a Blazor App and use it in App.razor like this:

    //...
    <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    //...
    <LayoutView Layout="@typeof(MainLayout)">
    //...
    

    Note that if you do this, your default page will be a Razor Component with @page "/" defined instead of Index.cshtml.