Serving interactive Razor component through Minimal API endpoint - in .NET 8. Both Server and WebAssembly.
Based on the dotnet new webapi
template.
Adds extension method that exposes the blazor.web.js
script as a static file.
To enable client WebAssembly support, there is another extension method that serves those files, including dotnet.js
.
Guides for Server and WebAssembly below.
Endpoints: http://localhost:5277/server and http://localhost:5277/wasm?incrementBy=2
FAQ and Links to resources at the bottom.
Created components:
Counter
- Interactive on the server.MyPage
- equivalent to anindex.html
page (Server-side rendered)
Register Razor component services:
builder.Services.AddRazorComponents()
.AddServerComponents();
Serve the Blazor JS script:
app.UseBlazorWebJS()
Map endpoint:
app.MapGet("/test", () => new RazorComponentResult<BlazorMinimalApi.Components.MyPage>());
Map Blazor Hub - important for interactive Server components:
app.MapBlazorHub();
Adds the route serving the blazor.web.js
, which is essential to all interactivity.
Based on this file.
You need to restructure your solution into having one Server project, and one Client project (for WebAssembly).
First. Create a standalone Blazor WebAssembly project for your client-side code.
dotnet new blazorwasm
Reference the client WebAssembly project from the Server project.
Add package reference:
dotnet add package Microsoft.AspNetCore.Components.WebAssembly.Server --prerelease
or add this to the .csproj
:
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.0-rc.1.*" />
Update the Program.cs
by adding a call to AddWebAssemblyComponents
:
builder.Services.AddRazorComponents()
.AddServerComponents()
.AddWebAssemblyComponents();
Use custom extension method that maps endpoint that exposes Blazor framework files.
app.UseBlazorWebAssemblyRenderMode();
Then set the render mode of, for instance, Counter
.
@attribute [RenderModeWebAssembly]
Or through the directive:
<Counter @rendermode="@RenderMode.WebAssembly" />
It is important that the WebAssembly component lives in the client project, otherwise it will not run in the browser.
Recommended for ordinary apps
You can enable the standard page component routing, which works for both SSR and interactive pages. This is provided that you have declared the router in the root App
component.
app.MapRazorComponents<App>()
.AddWebAssemblyRenderMode()
.AddServerRenderMode()
.AddAdditionalAssemblies(typeof(Counter).Assembly);
The router in App.razor
:
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
</RouteView>
</Found>
</Router>
And add the @page
directive to your page components:
@page "/my-route"
No. It is not supported. Though the possibility to support it is there.
What is currently lacking in .NET 8 RC1, it that there is no way to map the required JavaScript files outside the specific APIs what the Blazor team had constructed.
Other than adding extension methods that map those static files, there is no magic here.
Since it maps components to routes automatically - and you probably want control over the endpoints.
Why must I put the interactive component in a component that is served as static SSR?
Because you need a static page within which you can host the interactive component - similar to an index.html
. A structure of content which isn't affected by the interactivity,
This also re-assures that the script gets loaded first, and not reloaded with any interactive component.
Page layouts are applied in combination with Blazor Router
and RouteView
. We aren't using, and we can't use this here.
This is thus no direct replacement for MVC and Razor Views.
If layouts are important to you, then I recommend you to consider routable page components. (See Add routable pages above)
Yes. It should just work since it is being registered with the Blazor services.
builder.Services.AddRazorComponents();
I'm not sure whether this will work with RenderModeAuto
.