10

I am migrating a Blazor Server App (.Net 7) to the new Blazor Web App (.Net 8).

The project also includes some Razor pages (cshtml) which I now would like to migrate to the new Static Server Rendering (SSR).

Is it possible to declare the global rendermode "InteractiveServer" in the routes component: <Routes @rendermode="InteractiveServer" /> and overriding some components to use rendermode "StaticServer"? The option does not seem to be available in the Enumeration.

The other option would be to not set the global rendermode "InteractiveServer", but declare it per component. I am currently trying to get this to work, but it is breaking a lot of the existing functionality so I would prefer it the other way around.

So in short, how can I set a global rendermode "InteractiveServer" and override it to use "StaticServer" for a few pages/components?

4

3 Answers 3

10

There are two ways to achieve that.

Case 1. To be used if the Routes of all pages that shall use StaticServer start with the same Route-Segment (i.e. are in the same folder).

If for example all Pages in the "Account" Folder shall use StaticServer rendermode

In App.razor add the following

@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;

private IComponentRenderMode? RenderModeForPage =>
    HttpContext.Request.Path.StartsWithSegments("/Account")
        ? null
        : InteractiveServer;
}

and set

<Routes @rendermode="RenderModeForPage" />

a render mode of "null" means it will use StaticServer rendermode.

Reference

Case2. To be used if the pages that shall use StaticServer rendering are scattered all over the place.

Create a StaticSsrLayout.razor with the following content

@inherits LayoutComponentBase
@layout MainLayout
@inject NavigationManager NavigationManager

@if (HttpContext is null)
{
    <p>Loading...</p>
}
else
{
    @Body
}

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            NavigationManager.Refresh(forceReload: true);
        }
    }
}

Set this Layout for all pages that shall use StaticServer rendering

@layout StaticSsrLayout

In App.razor add the following

@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;

private IComponentRenderMode? RenderModeForPage =>
    HttpContext.GetEndpoint()?.Metadata.GetMetadata<RenderModeAttribute>()?
        .Mode;
}

And set

<Routes @rendermode="RenderModeForPage" />

Reference

Sign up to request clarification or add additional context in comments.

5 Comments

Very nice answer! for those who struggle implementing case1, make sure that you use @page /Account/page-name in your static pages.
@René, god bless you! I really taught for a moment, that the annotation in routes is a all or nothing option. Blazor is already clunky and that would be the cherry on the cake.
@René Question, if I render in ssr, my app bar is not working anymore, is there a way to solve this?
How to handle Logout? Because when you access Logout link HttpContext will be null
I've managed by moving all authentication login in a different area like described here
2

When using version 9 and up, if you don't want to rely on a specific path but really want to decide on a page-by-page basis you can use @attribute [ExcludeFromInteractiveRouting] on the static pages.

You will still need the PageRenderMode in the Router as described in the documentation:
Static SSR pages in an interactive app

1 Comment

This is great, thanks for sharing Henk 🙏
1

In regard to what René wrote in their answer. If you want multiple paths for case 1, you can do like this:

     private IComponentRenderMode? GetRenderMode(PathString pathString){
        IComponentRenderMode? StaticServer = null;
        bool isAccountPath = pathString.StartsWithSegments("/account");
        bool isSettingsPath = pathString.StartsWithSegments("/settings");
        if(isAccountPath || isSettingsPath) return StaticServer;
        return InteractiveServer;
     }
    
    private IComponentRenderMode? RenderModeForPage => GetRenderMode(HttpContext.Request.Path);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.