Skip to content

Support for multiple Blazor Web apps per server project #52216

@adaris-it

Description

@adaris-it

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

Quite often an application consists of several frontend apps which all need to access the same backend API. The new Blazor 8 template in VS assumes only one client app and distributes the razor files involved into 2 projects (the prerendering part is in the server project, the rest is in the client project).

So if I have 3 different frontend apps in Blazor 8, I'd need to have 3x2 = 6 projects, and each server project would essentially duplicate a lot of the shared logic, like authentication etc. Of course I could deploy a 7th project hosting only the common concerns like authentication, but for smaller projects this is overkill and poses new obstacles.

In ASP.NET Core 7 this problem was already solved:
https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/multiple-hosted-webassembly?view=aspnetcore-7.0&pivots=port-domain

I tried applying the same principle to Blazor 8, but it always results in an AmbiguousMatchException because both client apps register identical routes using the @page directive (like "/" etc.)

Describe the solution you'd like

The following code should work without any issues since I'm isolating the two clients using a request filter, as proposed in the ASP.NET 7 tutorial.

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseStaticFiles();
            app.UseAntiforgery();

            app.MapWhen(ctx => ctx.Request.Host.Port == 7282, client1 =>
            {
                client1.Use((ctx, nxt) =>
                {
                    if (!ctx.Request.Path.Value!.Contains("blazor.web.js"))
                    {
                        ctx.Request.Path = "/Client1" + ctx.Request.Path;
                    }
                    return nxt();
                });

                client1.UseStaticFiles();
                client1.UseStaticFiles("/Client1");
                //client1.UseRouting(); //<--- needed???
                client1.UseEndpoints(endpoints =>
                {
                    endpoints.MapRazorComponents<AppClient1>()
                        .AddInteractiveServerRenderMode()
                        .AddInteractiveWebAssemblyRenderMode()
                        .AddAdditionalAssemblies(typeof(Client.Pages.Counter).Assembly);
                });
            });


            app.MapWhen(ctx => ctx.Request.Host.Port == 7283, client2 =>
            {
                client2.Use((ctx, nxt) =>
                {
                    if (!ctx.Request.Path.Value!.Contains("blazor.web.js"))
                    {
                        ctx.Request.Path = "/Client2" + ctx.Request.Path;
                    }                    
                    return nxt();
                });

                client2.UseStaticFiles();
                client2.UseStaticFiles("/Client2");
                //client2.UseRouting(); //<--- needed???
                client2.UseEndpoints(endpoints =>
                {                    
                    endpoints.MapRazorComponents<AppClient2>()
                        .AddInteractiveServerRenderMode()
                        .AddInteractiveWebAssemblyRenderMode()
                        .AddAdditionalAssemblies(typeof(MultiClientTest.SecondClient.Pages.Counter).Assembly);
                });
            });
            
            app.Run();

Alternatively you could offer an optional builtin feature for isolating multiple client apps, like so:

app.MapRazorComponents<AppClient1>(ctx => ctx.Request.Host.Port == 7282)
app.MapRazorComponents<AppClient2>(ctx => ctx.Request.Host.Port == 7283)

I'm aware that this could still lead to ambiguous route mappings if the request filters aren't mutually exclusive; but then the framework would just throw an exception as it already does today.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Pillar: Dev ExperiencePriority:1Work that is critical for the release, but we could probably ship withoutarea-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-application-parts

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions