visual-studiodockerblazor-client-side

Debug blazor wasm using visual studio container tools


I've been using blazor wasm (hosted by aspnet core) in some of my projects for a while now. Since dotnet core I prefer to run my apps in containers. Visual studio has container and orchestration support, I've added this to my blazor solution and it works fine in release configuration.

However when I try to use the debug configuration (aka container fast mode) I get the following error:

System.ArgumentException: The path must be absolute. (Parameter 'root')
   at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters)
   at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root)
   at Microsoft.AspNetCore.Builder.BlazorHostingApplicationBuilderExtensions.UseClientSideBlazorFiles(IApplicationBuilder app, String clientAssemblyFilePath)
   at Microsoft.AspNetCore.Builder.BlazorHostingApplicationBuilderExtensions.UseClientSideBlazorFiles[TClientApp](IApplicationBuilder app)
   at BlazorWasmOnDocker.Server.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in D:\OpenSource\aspnetcore-apis\BlazorWasmOnDocker\BlazorWasmOnDocker\Server\Startup.cs:line 36
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)

I've seen multiple github issues being created for this e.g. https://github.com/aspnet/AspNetCore/issues/9704#issuecomment-544272050 but since blazor wasm isn't out of beta yet, these issues haven't been resolved.

How can I run blazor wasm hosted by asp as a container in fast mode?


Solution

  • To isolate this problem I've created a blazor wasm app that's hosted in ASP.net core by using the latest visual studio template (blazor 3.1 preview 4) and the lastest visual studio 2019 preview.

    After schaffolding a solution I added docker support and orchestration support in visual studio. This got me a setup that'll work when ran in release mode.

    To fix debug mode/container fast mode I read up on how visual studio runs containers in debug and release mode. See https://aka.ms/containerfastmode to understand how Visual Studio uses the generated Dockerfile to build your images for faster debugging.

    In a nutshell: when using release mode visual studio builds your dockerfile and thus your app is created build and publishes in the container itself which will create an app that contains your asp server and blazor client in /app.

    When using debug mode visual studio will only run the first stage of your dockerfile and then mount your 'server' project into the container. It then builds your 'server' project on your machine (this is faster then building it in the container), since the server project is mounted the compiled results are also in the container. Visual studio then starts a remote debugging session in the container which starts your app.

    The debug setup differs from the release setup in that there's no publish when debugging, and thus the blazor client isn't copied into your asp server app but is linked with a generated blazor config file (it's in your bin dir, mine is named BlazorWasmOnDocker.Client.blazor.config).

    Since the build ran outside of the container, the generated blazor.config also created links that only work outside of the container. For my setup it was something like:

    D:\Software\repos\aspnetcore-apis\BlazorWasmOnDocker\BlazorWasmOnDocker\Client\BlazorWasmOnDocker.Client.csproj

    And here in lies the problem, or actually 2 problems:

    1. The client project isn't mounted in the container
    2. The configured location of the blazor project is incorrect for running in a container

    Fixing the first problem can be done by creating a debug docker-compose.yml file (call it docker-compose.vs.debug.yml so visual studio will use it when debugging) which adds a mount to the client project:

    version: '3.4'
    
    services:
      blazorwasmondocker.server:
        volumes:
          - ./BlazorWasmOnDocker/Client:/Client
    

    Fixing the second problem can be done by correcting the paths to the client project in the generated blazor config after a debug build. I did so in the program.cs you could also do it in the container startup or post build hook.

    
            public static void Main(string[] args)
            {
    #if DEBUG
                const string blazorConfigPath = @"/app/bin/Debug/netcoreapp3.1/BlazorWasmOnDocker.Client.blazor.config";
                var blazorConfig = File.ReadAllText(blazorConfigPath);
                blazorConfig = Regex.Replace(blazorConfig, @"[a-zA-Z]:\\.+?\\Client\\", "/Client/")
                    .Replace('\\', '/');
                File.WriteAllText(blazorConfigPath, blazorConfig);
    #endif
    
                BuildWebHost(args).Run();
            }
    

    As a reference I've pushed a demo project to github and put the fix in 1 commit: https://github.com/Rora/aspnetcore-apis/commit/7ef4682d1466bd94faaba9adafac2cb0f6f59723