Search code examples
c#blazorblazor-server-side

Blazor, .NET 8 MapRazorComponents fallback


We are migrating Blazor Server application to .NET 8. Previously, we've used a custom router in _Host.cshtml to resolve routes not defined via @page (convention-based routing, similar to MVC). In the new hosting model, with MapRazorComponents I can't find a way to do the same, but for a Razor component, in this case App. Is this possible or do we have to fall back to _Host.cshtml?


Solution

  • You could use Custom router component to achieve your requirement that will maps URLs to specific Razor components without altering the URL.

    CustomRouter component will capture the url path and dynamically resolves and renders the appropriate Razor component based on custom logic.

    CustomRouter.razor:

    @page "/{*path}"
    @inject NavigationManager Navigation
    
    @code {
        [Parameter]
        public string Path { get; set; }
    
        private Type _componentType;
    
        protected override void OnParametersSet()
        {
            // Resolve the component type based on the Path
            _componentType = ResolveComponent(Path);
        }
    
        private Type ResolveComponent(string path)
        {
            return path switch
            {
                "foo" => typeof(FooComponent),
                "bar" => typeof(BarComponent),
                _ => typeof(NotFoundComponent)
            };
        }
    }
    
    @if (_componentType != null)
    {
        <DynamicComponent Type="_componentType" />
    }
    else
    {
        <p>Component not found</p>
    }
    

    App.razor:

    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <CustomRouter />
            </LayoutView>
        </NotFound>
    </Router>
    

    Program.cs:

    using BlazorCustomRouter;
    using BlazorCustomRouter.Data;
    using Microsoft.AspNetCore.Components;
    using Microsoft.AspNetCore.Components.Web;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
    builder.Services.AddSingleton<WeatherForecastService>();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.MapBlazorHub();
    app.MapFallbackToPage("/_Host");
    
    app.Run();
    

    This will work with .net 8 and it will also create similar to MVC convention-based routing. If you prefer to keep the routing more declarative or need to more complex routing patterns, you might consider implementing middleware to handle some of the routing before it reaches Blazor.