jsakamoto / BlazorWasmPreRendering.Build

When you publish your Blazor Wasm app, this package pre-renders and saves the app as static HTML files in your public folder.
https://jsakamoto.github.io/BlazorWasmPreRendering.Build/
Mozilla Public License 2.0
261 stars 15 forks source link

System.InvalidOperationException: 'RemoteNavigationManager' has not been initialized. #44

Closed fingers10 closed 4 months ago

fingers10 commented 4 months ago

Hi @jsakamoto ,

I recently noticed that the Publishing fails when I have NavigationManager injected inside a class which is not a component.

For example,

public class SlugService(NavigationManager navigationManager)
{
    public string GetSlug()
    {
        var slug = navigationManager.Uri.ToString().Split('/').Last();
        ArgumentException.ThrowIfNullOrWhiteSpace(slug, nameof(slug));
        return slug;
    }
}

Register this in Program.cs

services.AddSingleton(serviceProvider => new SlugService(serviceProvider.GetRequiredService<NavigationManager>()));

This setup works fine locally when running but fails during publish.

Here is the exception details:

Getting http://127.0.0.1:5050/blogs/unit-testing-filters-in-asp-net-webapi...
Error: ROR] The HTTP status code was not OK. (it was (500)InternalServerError.)
      System.InvalidOperationException: 'RemoteNavigationManager' has not been initialized.
         at Microsoft.AspNetCore.Components.NavigationManager.AssertInitialized()
         at Microsoft.AspNetCore.Components.NavigationManager.get_Uri()
         at SharedComponents.SlugService.GetSlug()
         at BaseComponents.Content.OnInitialized()
         at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
         at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
         at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
         at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
         at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
         at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
         at Microsoft.AspNetCore.Components.Endpoints.SSRRenderModeBoundary.SetParametersAsync(ParameterView parameters)
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters)
         at Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.BeginRenderingComponent(IComponent component, ParameterView initialParameters)
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.<>c__DisplayClass35_0.<PrerenderComponentAsync>b__0()
         at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<InvokeAsync>g__Execute|9_0[TResult](ValueTuple`3 state)
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.PrerenderComponentAsync(HttpContext httpContext, Type componentType, IComponentRenderMode prerenderMode, ParameterView parameters, Boolean waitForQuiescence)
         at Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentExtensions.RenderComponentAsync(IHtmlHelper htmlHelper, Type componentType, RenderMode renderMode, Object parameters)
         at AspNetCoreGeneratedDocument.Pages__Host.ExecuteAsync() in C:\Projects\My\Blazor\PreRendering\BlazorWasmPreRendering.Build.WebHost\Pages\_Host.cshtml:line 5
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
         at Toolbelt.Blazor.HeadElement.Middlewares.HeadElementServerPrerenderingMiddleware.InvokeAsync(HttpContext context, IHeadElementHelperStore store)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

GitHub Actions Build: https://github.com/ILoveDotNet/ilovedotnet/actions/runs/9917040406/job/27400021468

Please can you assist me on this?

jsakamoto commented 4 months ago

Hi @fingers10, thank you for letting me know that! I'll investigate this problem and resolve it later. I appreciate your patience.

jsakamoto commented 4 months ago

Hi @fingers10,

You should change your code from

services.AddSingleton(serviceProvider => new SlugService(serviceProvider.GetRequiredService<NavigationManager>()));

to

services.AddScoped(serviceProvider => new SlugService(serviceProvider.GetRequiredService<NavigationManager>()));

because your Blazor app code is running in a Blazor Server app during the pre-rendering process.

fingers10 commented 4 months ago

Many thanks for your time and response. I'll check this and keep you posted.

fingers10 commented 4 months ago

This works. Many thanks for your time and support. Much appreciated.

fingers10 commented 4 months ago

This works. Many thanks for your time and support. Much appreciated.