Blazor WebAssembly 3.2.0 Preview 4 release now available

Daniel Roth

A new preview update of Blazor WebAssembly is now available! Here’s what’s new in this release:

  • Access host environment during startup
  • Logging improvements
  • Brotli precompression
  • Load assemblies and runtime in parallel
  • Simplify IL linker config for apps
  • Localization support
  • API docs in IntelliSense

Get started

To get started with Blazor WebAssembly 3.2.0 Preview 4 install the latest .NET Core 3.1 SDK.

NOTE: Version 3.1.201 or later of the .NET Core SDK is required to use this Blazor WebAssembly release! Make sure you have the correct .NET Core SDK version by running dotnet --version from a command prompt.

Once you have the appropriate .NET Core SDK installed, run the following command to install the updated Blazor WebAssembly template:

dotnet new -i Microsoft.AspNetCore.Components.WebAssembly.Templates::3.2.0-preview4.20210.8

If you’re on Windows using Visual Studio, we recommend installing the latest preview of Visual Studio 2019 16.6. For this preview you should still install the template from the command-line as described above to ensure that the Blazor WebAssembly template shows up correctly in Visual Studio and on the command-line.

That’s it! You can find additional docs and samples on https://blazor.net.

Upgrade an existing project

To upgrade an existing Blazor WebAssembly app from 3.2.0 Preview 3 to 3.2.0 Preview 4:

  • Update all Microsoft.AspNetCore.Components.WebAssembly.* package references to version 3.2.0-preview4.20210.8.
  • Update any Microsoft.AspNetCore.Components.WebAssembly.Runtime package references to version 3.2.0-preview5.20210.1
  • Replace package references to Microsoft.AspNetCore.Blazor.HttpClient with System.Net.Http.Json and update all existing System.Net.Http.Json package references to 3.2.0-preview5.20210.3.
  • Add @using System.Net.Http.Json to your _Imports.razor file and update your code as follows:

    Microsoft.AspNetCore.Blazor.HttpClient System.Net.Http.Json
    GetJsonAsync GetFromJsonAsync
    PostJsonAsync PostAsJsonAsync
    PutJsonAsync PutAsJsonAsync

    Calls to PostAsJsonAsync and PutAsJsonAsync return an HttpResponseMessage instead of the deserialized response content. To deserialize the JSON content from the response message, use the ReadFromJsonAsync<T> extension method: response.content.ReadFromJsonAsync<WeatherForecast>().

  • Replace calls to AddBaseAddressHttpClient in Program.cs with builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });.

  • Update service registrations that depend on IAccessTokenProvider to be scoped services instead of singleton services.

You’re all set!

Access host environment during startup

The WebAssemblyHostBuilder now exposes IWebAssemblyHostEnvironment through the HostEnvironment property, which surfaces details about the app environment (Development, Staging, Production, etc.) during startup. If the app is hosted in an ASP.NET Core app, the environment reflects the ASP.NET Core environment. If the app is a standalone Blazor WebAssembly app, the environment is specified using the blazor-environment HTTP header, which is set to Development when served by the Blazor dev server. Otherwise, the default environment is Production.

New convenience extension methods on IWebAssemblyHostEnvironment make it easy to check the current environment: IsProduction(), IsDevelopment(), IsStaging(). We’ve also added a BaseAddress property to IWebAssemblyHostEnvironment for getting the app base address during startup when the NavigationManager service isn’t yet readily available.

Logging improvements

The WebAssemblyHostBuilder now exposes a Logging property of type ILoggingBuilder that can be used to configure logging for the app, similar to how you would configure Logging in an ASP.NET Core app on the server. You can use the ILoggingBuilder to set the minimum logging level and configure custom logging providers using extension methods in the Microsoft.Extensions.Logging namespace.

Brotli precompression

When you publish a Blazor WebAssembly app, the published and linked output is now precompressed using Brotli at the highest level to further reduce the app size and remove the need for runtime compression. ASP.NET Core hosted apps seamlessly take advantage of these precompressed files. For standalone apps, you can configure the host server to redirect requests to the precompressed files. Using the precompressed files, a published Blazor WebAssembly is now 1.8MB, down from 2MB in the previous preview. A minimal app without Bootstrap CSS reduces to 1.6MB.

Load assemblies and runtime in parallel

Blazor WebAssembly apps now load the assemblies and runtime in parallel saving some precious milliseconds off the app load time.

Simplify .NET IL linker config for apps

You can optionally provide a .NET IL linker config file for a Blazor WebAssembly app to customize the behavior of the linker. Previously, specifying a linker config file for your app would override the customizations built into Blazor that are necessary for apps to function property. App specific linker configuration is now treated as additive to the linker configuration provided by Blazor.

Localization support

Blazor WebAssembly apps now support localization using .NET resource files (.resx) and satellite assemblies. Blazor WebAssembly apps set the current culture using the user’s language preference. The appropriate satellite assemblies are then loaded from the server. Components can then be localized using the ASP.NET Core localization APIs, like IStringLocalizer<TResource> and friends. For more details on localizing Blazor WebAssembly apps, see Globalization and localization.

API docs in IntelliSense

The API docs for the various Blazor WebAssembly APIs are now available through IntelliSense:

API docs in IntelliSense

Known issues

Debugging limitations

Thank you everyone who has been trying out the new Blazor WebAssembly debugging support and sending us your feedback! We’ve made some progress in this release, but there are still a number of limitations with the current debugging experience in Visual Studio and Visual Studio Code. The following debugging features are still not yet fully implemented:

  • Inspecting arrays
  • Hovering to inspect members
  • Step debugging into or out of managed code
  • Full support for inspecting value types
  • Breaking on unhandled exceptions
  • Hitting breakpoints during app startup

We expect to continue to improve the debugging experience in future releases.

Help improve the Blazor docs!

We’ve received a some feedback from the in-product Blazor survey that the Blazor docs could use some improvement. Thank you for this feedback! We know that docs are a critical part of any software development framework, and we are committed to making the Blazor docs as helpful as we can.

We need your help to understand how to best improve the Blazor docs! If you’d like to help make the Blazor docs better, please do the following:

  • As you read the Blazor docs, let us know where we should focus our efforts by telling us if you find a topic helpful or not using the helpfulness widget at the top of each doc page:

    Doc helpfulness

  • Use the Feedback section at the bottom of each doc page to let us know when a particular topic is unclear, inaccurate, or incomplete.

    Doc feedback

  • Comment on our Improve the Blazor docs GitHub issue with your suggestions for new content and ways to improve the existing content.

Feedback

We hope you enjoy the new features in this preview release of Blazor WebAssembly! Please let us know what you think by filing issues on GitHub.

Thanks for trying out Blazor!

50 comments

Discussion is closed. Login to edit/delete existing comments.

  • Sinior Muczaczo 0

    I have a rather technical question – which commit in the repository can be considered as the source for Blazor WebAssembly 3.2.0 Preview 4 release?
    Does the repository use any standardized way of commit marking (e.g. tagging), from which an official release is created?
    I am asking because I would like to compare, for example, the source codes for the Blazor WebAssembly 3.2.0 Preview 3 version with the codes for the e.g. Blazor WebAssembly 3.2.0 Preview 4 version…

    What is it like with repositories? From what I see there is https://github.com/dotnet/blazor/commits/master (for which there is information that “Blazor moved to the ASP.NET Core repo” but there are some “fresh” commits) and e.g. https://github.com/dotnet/aspnetcore/commits/blazor-wasm

  • Andy Chopra 0

    Dan, I just installed the new version and tried to play with it. I am noticing a weird caching behavior, where even minor text/html changes are not getting reflected in the browser. Here is the issue in Github: issue

    • Daniel RothMicrosoft employee 0

      Thanks for trying out the preview! We’ll reply on the GitHub issue.

      • Daniel RothMicrosoft employee 0

        There was an issue with the Microsoft.AspNetCore.Components.WebAssembly.Build package that was uploaded for the 3.2 Preview 4 release. The package has now been replaced with a fixed package. To get the fix, clear your local nuget cache (dotnet nuget locals all -c) and then restore again.

  • Ben Hayat 0

    Blazor is turning into a first class product.
    Can’t wait to see the full blazor running with .Net 5.

    Thank you Blazor Team!
    ..Ben

  • Benjamin Vertonghen 0

    Looking good, all set and ready to go!
    However, I’m wondering why we add the HttpClient as a Singleton, specifically :
    Replace calls to AddBaseAddressHttpClient in Program.cs with

     builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

    Why don’t we make use of the HttpClientFactory?

                
    builder.Services.AddHttpClient("app", c =>
    {
       c.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
    });

    Thanks!

    • Daniel RothMicrosoft employee 0

      Hi Benjamin. Using IHttpClientFactory in a Blazor WebAssembly app is perfectly fine and in many cases is desirable if you need to manage multiple HttpClient configurations. We don’t include it by default simply because of the added dependency.

  • Howard Richards 0

    Are there upgrade steps missing, or is my app a bit out of date? I currently have this in the ASP.NET Core startup:

     services.AddMvc().AddNewtonsoftJson();
     services.AddSignalR();
    
     services.AddResponseCompression(opts =>
       {
         opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                        new[] { "application/octet-stream" });
       });

    I assume the Brotli compression means I don’t need the response compression? I did dotnet new with the new templates, the startup just has

                services.AddControllersWithViews();
    

    Ref: startup.cs

  • Piercarlo Schiavo - BIsolution 0

    Hi daniel,

    I updated to the new release, but I´m getting following error:

    blazor.webassembly.js:1 Microsoft.JSInterop.JSException: Could not find 'getSatelliteAssemblies' in 'window.window.Blazor._internal'.
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1 Error: Could not find 'getSatelliteAssemblies' in 'window.window.Blazor._internal'.
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at https://localhost:44335/_framework/blazor.webassembly.js:1:9067
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at Array.forEach ()
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at Object.p [as findJSFunction] (https://localhost:44335/_framework/blazor.webassembly.js:1:9028)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at _mono_wasm_invoke_js_unmarshalled (https://localhost:44335/_framework/wasm/dotnet.3.2.0-preview5.20210.1.js:1:165380)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at do_icall (wasm-function[6047]:0x1112f3)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at do_icall_wrapper (wasm-function[1900]:0x52abf)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at interp_exec_method (wasm-function[1123]:0x2585f)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at interp_runtime_invoke (wasm-function[5652]:0xf8d5b)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at mono_jit_runtime_invoke (wasm-function[5106]:0xdf5a3)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1     at do_runtime_invoke (wasm-function[1412]:0x3d8b6)
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1   at Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.InvokeUnmarshalled[T0,T1,T2,TResult] (System.String identifier, T0 arg0, T1 arg1, T2 arg2)  in :0 
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1   at Microsoft.AspNetCore.Components.WebAssembly.Services.WebAssemblyJSRuntimeInvoker.InvokeUnmarshalled[T0,T1,T2,TResult] (System.String identifier, T0 arg0, T1 arg1, T2 arg2)  in :0 
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1   at Microsoft.AspNetCore.Components.WebAssembly.Hosting.SatelliteResourcesLoader.LoadSatelliteAssembliesForCurrentCultureAsync ()  in :0 
    p.printErr @ blazor.webassembly.js:1
    blazor.webassembly.js:1   at Microsoft.AspNetCore.Components.WebAssembly.Hosting.EntrypointInvoker.InvokeEntrypoint (System.String assemblyName, System.String[] args, Microsoft.AspNetCore.Components.WebAssembly.Hosting.SatelliteResourcesLoader satelliteResourcesLoader)  in :0 

    some suggestions ?

    • Fabian 0

      same here – did you find out something ?

      I get those errors during compilation despite that I updated Blazor WebAssembly template to preview 4:

      MyProject depends on Microsoft.AspNetCore.Components (>= 3.2.0-preview4.20210.8) but Microsoft.AspNetCore.Components 3.2.0-preview4.20210.8 was not found. An approximate best match of Microsoft.AspNetCore.Components 5.0.0-preview.1.20124.5 was resolved.

      MyProject depends on Microsoft.JSInterop (>= 3.2.0-preview4.20210.8) but Microsoft.JSInterop 3.2.0-preview4.20210.8 was not found. An approximate best match of Microsoft.JSInterop 5.0.0-preview.1.20120.4 was resolved.

    • David Calvo 0

      Another nuget installed?
      In my case a component to upload files

        • Nemanja Stolic 0

          Hi, I had the same issue.
          To solve the problem I installed Visual Studio 16.16.0 Preview 3.0,
          and made sure that all DLLs are on 3.2.0 Preview 4 or Preview 5 if available.
          Also please check that you didn’t upgrade any of the Microsoft.* DLLs to version 5.x

    • Dariusz WesoÅ‚owski 0

      Had the same issue.
      For me running the solution w/o debugging is a valid workaround. It’s a known issue if you use authentication.

      • Daniel RothMicrosoft employee 0

        Hi Dariusz. Is there a GitHub issue that tracks the specific details of the issue you are seeing? If so, could you please reference it here so that folks can track it’s status?

        • Dariusz WesoÅ‚owski 0

          Sorry – I misunderstood some old (already closed) issue. Nevertheless – the workaround coincidentally worked for me.
          Updating the WebAssembly packages to preview 5 and Microsoft.AspNetCore.Components.Authorization to 5.0.0.preview.3 fixed the debugger.

          • Daniel RothMicrosoft employee 0

            Hi Dariusz. Please note that we don’t recommend mixing .NET 5 preview bits with Blazor WebAssembly at the moment. Instead, I suggest using the latest .NET Core 3.1 versions of packages like Microsoft.AspNetCore.Components.Authorization.

    • taurius litvinavicius 0

      After many hours of struggle, I reloaded with developer tools on and it worked. But what about a normal user, who cannot clear the cache like that?

    • Patrick Szalapski 0

      Same here. Anyone fix this in the last three weeks?

      • Daniel RothMicrosoft employee 0

        Hi Patrick. Can you check to see if you’re getting a cached copy of blazor.webassembly.js in the browser? If yes, please try clearing the cache and see if that resolves the issue. If it doesn’t, file an issue on GitHub and we’ll take a look: https://github.com/dotnet/aspnetcore/issues.

  • Morten Meisler 0

    Great great – I was just getting nervous it would not come this week 😀

    I upgraded my project sucessfully.

    Only minor issue (which was probably a fault at my end):
    I had services defined like this:

    builder.Services.AddSingleton<GraphClient>();

    injecting the IAccessTokenProvider, but since that is scoped, I had to change my services to this:

    builder.Services.AddScoped<GraphClient>();

    And also this #20938 is fixed. Great!

    • John Linstrum 0

      I also ran into this issue. I’m sure it just means that the new version is less forgiving of bad code. Nonetheless, perhaps enough folks will run into it that some sort of mention here would be beneficial?

      • Daniel RothMicrosoft employee 0

        Hi John. The lifetime of the IAccessTokenProvider service was changed from Singleton to Scoped. I went ahead and added a mention of this in migration steps.

  • Damiano CuriaMicrosoft employee 0

    Hi Daniel,
    I have upgraded my solution to Preview 4.
    Everything works, even the debugger with PWA.

    Apart from the notes you have written, I have created a new empty solution with the new templates and found multiple semplifications in the project structure that are not listed in this article.
    I have applied them as well, and everything seems to be working fine as well.

    Thank you for your efforts in making Blazor such a wonderful piece of tech!

    • Daniel RothMicrosoft employee 0

      Hi Damiano. I’m happy to hear your upgrade went smoothly! We did have issues with debugging PWAs in the previous preview, which was fixed for this release. It’s great to hear that’s now working for you! If you think there are additional migration steps we should add let me know!

  • iulik iulik 0

    HI, do you plan to compile blazor like svelte? is too much 6MB for a small app.

    • Daniel RothMicrosoft employee 0

      A published Blazor WebAssembly app is actually a lot smaller than 6MB. When the app is published. Blazor will run the .NET assemblies through a .NET IL linker that removes unneeded code and then aggressively compresses the app files using Brotli. A minimal Blazor WebAssembly app (no Bootstrap or other accessories) is only about 1.6MB. After the initial download the runtime and framework files are cached so subsequent loads are much quicker. That said, we’re always looking at new ways to make Blazor better and there are some interesting ideas in Svelte that are worth learning from.

  • Ben Hayat 0

    Dan, how is gRPC-Web coming when WASM goes GA in May?

    • Daniel RothMicrosoft employee 0

      Hi Ben. The gRPC-web support for .NET is coming along in the https://github.com/grpc/grpc-dotnet/ repo. They are working towards shipping a stable release, but there’s no concrete release date yet.

Feedback usabilla icon