dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.21k stars 9.95k forks source link

How to set prerender on all client WASM portion of a Blazor Web App #57532

Closed genifycom closed 3 weeks ago

genifycom commented 3 weeks ago

Is there an existing issue for this?

Describe the bug

I am deploying a Blazor Web App (with Interactive render mode = WebAssembly). I do not want any signalR (because this is serverless).

If I add to Counter.razor

@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))

that works fine.

I want to make pre-render false for the whole client project (DI does not work for child components with pre-rendering). In order to set the whole client WASM app to no prerender, the documentation says to add to App.razor (which exists in the parent project).

<Routes @rendermode="@(new InteractiveWebAssemblyRenderMode(prerender: false))" />

But when I run this, I get a blank screen.

Console says:

Error: One or more errors occurred. (Root component type 'BlazorWebApp.Components.Routes' could not be found in the assembly 'BlazorWebApp'.) at Jn (marshal-to-js.ts:349:18) at Ll (marshal-to-js.ts:306:28) at 00b21c96:0x1f979 at 00b21c96:0x1be41 at 00b21c96:0xf00e at 00b21c96:0x1e693 at 00b21c96:0x1ee89 at 00b21c96:0xce5e at 00b21c96:0x44219 at e. (cwraps.ts:338:24)

Expected Behavior

Create a standard template Blazor Web App with render mode WebAssembly.

Make the WASM client not prerender.

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

javiercn commented 3 weeks ago

@genifycom thanks for contacting us.

Did you use per page interactivity or "global" interactivity. Those instructions are likely for global interactivity. If you used per page interactivity you can put @rendermode InteractiveWebAssembly(prerender:false) on _Imports.razor in the Client project (where the pages are located) and that will disable prerendering for all those pages.

genifycom commented 3 weeks ago

Ah, thank you for that clarification about the instructions being for "Global" interactivity.

So I tried adding

@rendermode InteractiveWebAssembly(prerender:false)

in the clients _Imports.razor

The complier gives me

BlazorWebApp\BlazorWebApp.Client_Imports.razor(12,13,12,36): error RZ1041: The 'rendermode' directive expects an identifier or explicit razor expression ("@()").

Can you point me to some documentation on how to use this approach please? I see there are project _Import.razor files, Components _Import.razor files and Component Pages _Import.razor files

Thank you

genifycom commented 3 weeks ago

To replicate my issue:

  1. Create a Blazor Web App with: Framework:. Net 8.0, Authentication Type: None, Interactive render mode: WebAssembly, Interactivity location: Per page/component
  2. In the Client project Program.cs add builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
  3. In the Client Counter.razor file in IncrementCount() add @using System.Net.Http @inject HttpClient Http

Change the IncrementCount signature from void to async Task and add: string url = "https://google.com"; var results = await Http.GetStringAsync(url);

  1. Run and click Counter. The error will indicate InvalidOperationException: Cannot provide a value for property 'Http' on type 'BlazorApp7.Client.Pages.Counter'. There is no registered service of type 'System.Net.Http.HttpClient'
  2. To fix this, you can change the Counter.razor item at the top from @rendermode InteractiveWebAssembly to @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false)) Counter will now work.

But, if you use Layouts or Child components and they use DI items, they will experience the same issue.

I am hoping that by making the entire Client WASM project prerender: false that this issue will go away.

genifycom commented 3 weeks ago

Actually, it turns out if you have an inject statement but never use the service, the WASM component will still fail when it prerenders.

This is unfortunate as otherwise we could use some prerender checks.

javiercn commented 3 weeks ago

@genifycom thanks for the additional details.

There are essentially two processes running (server and browser) any component that you want to use prerendering with, needs to be able to run in both.

genifycom commented 3 weeks ago

Hi Javier,

Yes I understand the concept but the aim here is to avoid any prerender for the WASM client. Indeed in my case, there are libraries that I only want to use with WASM.

It appears that what you are saying is that with the Blazor Web App template, it is not possible to completely eliminate prerendering for the Client project?

dotnet-policy-service[bot] commented 3 weeks ago

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.