Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Blazor right approach for having everything in wasm but at the same time also have a support for server page rendering for certain pages?

$
0
0

Goal/constraint is to have a SPA, everything in wasm (even router) but at the same time support pages on the server. Greatest flexibility.

Here I accomplished rendering rules by page locations:

  • If page is on client only, it will render InteractiveWebAssemblyRenderMode without prerender.
  • If page is on server only, it will render InteractiveServerRenderMode with prerender.
  • If page is on server and client, it will render InteractiveWebAssemblyRenderMode with prerender.

Pages on server that are also on client will be added as a link from the client.

Components on server:

Program.cs:

...app.MapRazorComponents<App>()    .AddInteractiveServerRenderMode()    .AddInteractiveWebAssemblyRenderMode();app.Use404FallbackToClient();app.Run();

ApplicationBuilderExtensions.cs:

public static void Use404FallbackToClient(this IApplicationBuilder builder){    builder.Use(async (context, next) =>    {        await next();        // Check if the response status code is 404 and the request path doesn't start with "/_framework"        if (context.Response.StatusCode == StatusCodes.Status404NotFound && !context.Request.Path.StartsWithSegments("/_framework"))        {            // Create a new endpoint for the Razor component rendering            var endpointFeature = context.Features.Get<IEndpointFeature>();            if (endpointFeature != null)            {                endpointFeature.Endpoint = new RouteEndpoint(                    async httpContext =>                    {                        context.Response.StatusCode = StatusCodes.Status200OK;                        // Render the Blazor component (in this case, App or your custom component)                        var result = new RazorComponentResult<App>();                        await result.ExecuteAsync(httpContext);                    },                    RoutePatternFactory.Parse("/404"),                    0,                    new EndpointMetadataCollection(new[] { new ComponentTypeMetadata(typeof(_404)) }),"404 Endpoint"                );            }            // Render the Razor component directly            await endpointFeature.Endpoint.RequestDelegate(context);        }    });}

App.razor:

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><base href="/" /><link rel="stylesheet" href="bootstrap/bootstrap.min.css" /><link rel="stylesheet" href="app.css" /><link rel="stylesheet" href="Sindikat.Web.styles.css" /><link rel="icon" type="image/png" href="favicon.png" /><HeadOutlet @rendermode="RenderModeForPage" /><RadzenTheme Theme="material" @rendermode="RenderModeForPage" /></head><body>        @if (ServerOnlyPage)        {<Routes @rendermode="RenderModeForPage" />        }        else        {<Sindikat.Web.Client.Components.Routes @rendermode="RenderModeForPage" />        }<script src="_framework/blazor.web.js"></script><script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script><script src="js/sindikatAppBundle.js"></script></body></html>    public partial class App    {        private static Assembly serverAssembly;        private static Assembly clientAssembly;        static App()        {            serverAssembly = typeof(Program).Assembly;            clientAssembly = typeof(Sindikat.Web.Client.ModuleDefinitions.Module).Assembly;        }        [CascadingParameter]        private HttpContext HttpContext { get; set; } = default!;        private IComponentRenderMode? RenderModeForPage { get; set; }        private bool ServerOnlyPage;        protected override void OnInitialized()        {            var endpointFeature = HttpContext.Features.Get<IEndpointFeature>();            var type = endpointFeature.Endpoint?.Metadata.GetMetadata<ComponentTypeMetadata>()?.Type;            var hasServerPage = type?.Assembly == serverAssembly;            var hasClientPage = clientAssembly.GetType($"Sindikat.Web.Client.Components.Pages.{type.Name}") != null;            ServerOnlyPage = hasServerPage && !hasClientPage;            var renderMode = type?.GetRenderMode();            if (renderMode != null)                RenderModeForPage = renderMode;            else                RenderModeForPage = ServerOnlyPage ?                    new InteractiveServerRenderMode() :                    new InteractiveWebAssemblyRenderMode(hasServerPage);        }    }

Routes.razor:

  @using Microsoft.AspNetCore.Components.WebAssembly.Hosting    @using Sindikat.Web.Client.Components<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><RouteFound RouteData="routeData" /></Found></Router>

Components on Client:

Home.razor:

I decided that all pages will only have page name and a component that will have page content.

    @page "/"<PageTitle>Home</PageTitle><Sindikat.Web.Client.Components.Home></Sindikat.Web.Client.Components.Home>

Routes.razor:

@using Microsoft.AspNetCore.Components.WebAssembly.Hosting<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><RouteFound RouteData="routeData" /></Found></Router>

404.razor:

@page "/404"

Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>