Blazor WebAssembly 3.2.0 Preview 4 release now available

Daniel

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

Comments are closed. Login to edit/delete your existing comments

  • Darren Ford

    I fired up a new Blazor WASM project using the latest template and added OidcAuthentication. My auth server is adding roles which can be seen in the JWT Bearer token that is found in the Session Storage. When using AuthorizeView or AuthorizeAttribute with Roles it is not picking up the roles from the access_token.

    Sample Claims from access_token when debugged with jwt.io debugger and outputting it in an AuthorizeView-Authorized block:

    Claim Type: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
    Claim Value: [“Reports”,”Administrator”,”Dashboard”,”Research”,”Inventory”,”Accounting”]

    These are added by some custom code in my Auth server. Is this the wrong claim Type for the roles to get picked up?

    Am I missing something here or is this broken?

    I found this Issue: https://github.com/dotnet/aspnetcore/issues/14930 that specifically talks about this. Since the WASM OIDC implementation is the client side of this, should it be able to handle the array format?

    When I only have one role assigned the process seems to work so this is indeed an issue with the fact that the ClaimTypes.Role claim contains an array. It appears to be a bug in the WASM side oidc claims parsing. It should be able to handle an array type for roles.

    Here’s a link to an IdentityServer4 issue talking about this: https://github.com/IdentityServer/IdentityServer4/issues/2999

  • Marina Reva

    Thanks for your work!
    Can I continue to use older PostJsonAsync extensions? Or with new PostAsJsonAsyncor instead of new ?
    I need to return objects in Post as in PostJsonAsync. Because these are processed objects on the server and their change is necessary on the client. so I need get back object after PostJsonAsync .

    • Daniel RothMicrosoft employee

      Hi Marina. The older PostJsonAsync methods that shipped as part of the Microsoft.AspNetCore.Blazor.HttpClient are being replaced with the new methods in System.Net.Http.Json. The new PostAsJsonAsync<T> method returns an HttpResponseMessage, but you can still deserialize the response body into a .NET object by calling ReadFormJsonAsync<T> on the response content, like this: response.content.ReadFromJsonAsync<WeatherForecast>()

  • Manoj Kumar

    Blazor performance is very good in mid and high end devices but in low end devices it is extremely poor, we started building a product on blazor, now we are worried about its performance.
    Mainly following things…
    . Json de-serialization is damn slow using NewtonSoft.
    . Moving data through methods from javascript to c# or c# to javascript also taking much time.

    Is blazor is recommended for low end devices which have 1.2Ghz speed and dual cores?

    • Daniel RothMicrosoft employee

      Hi Manoj.

      Have you tried using the new System.Text.Json serializer instead of Newtonsoft.Json? We moved Blazor to use System.Text.Json some time ago and it does provide some performance improvements.

      Also, if you need to push a lot of data through JavaScript interop there is a Blazor WebAssembly specific mechanism for unmarshalled interop calls: https://github.com/dotnet/aspnetcore/blob/master/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessRuntime.cs. It’s not well documented and it’s pretty low level, but it is available for advanced scenarios.

      The .NET runtime used by Blazor WebAssembly is doing IL interpretation – there’s no JIT – so this does affect the performance of CPU intensive workloads. For .NET 5 we are looking at adding support for ahead of time (AoT) compilation that we enable precompiling hot paths to WebAssembly as a way to improve runtime performance.

      I hope this helps!

      • Manoj Kumar

        Thanks you so much for the detailed reply…
        For us only concern is performance, apart from that blazor framework is helping us to build the product very quickly and deployments became very simple.
        Please give us better performance in upcoming versions and
        provide some articles for recommended way to develop blazor apps without hitting performance.

  • Paul Roskilly

    My Blazor App (3.2.0 Preview 4) runs fine locally using Visual Studio but when I try and deploy it to IIS I get an error, I have deployed it before when it was a 3.2.0 preview 3 app with no problems :

    error : Unhandled exception. Mono.Linker.Steps.XmlResolutionException: Failed to process XML description:
    1> —> Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: ‘Microsoft.AspNetCore.Blazor.HttpClient, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’
    1> —> Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: ‘Microsoft.AspNetCore.Blazor.HttpClient, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’
    1> at Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters)

    I followed the upgrade steps in this article, maybe it is something to do with removing the reference to Microsoft.AspNetCore.Blazor.HttpClient

    • Daniel RothMicrosoft employee

      Hi Paul. It does sound like something has gotten out of sync. If you delete your bin & obj folders and rebuild and republish, does that resolve the issue?

    • Daniel RothMicrosoft employee

      Also, it would be useful if we could take a look at what you have in your project file to make sure you don’t have any MSBuild additions that might be affecting things.

    • Nicolas Mesaritis

      Hi Paul

      We had the same issue while publishing the Blazor App.
      It seems the publish works only with Target Runtime: Portable.

  • Robert Leatherman

    Hello Daniel, successfully upgraded to preview 5, but wanted to leave the comment here because this is where the API calls were changed. I’m getting the following error calling my API’s GET method using the GetFromJsonAsync change in this version:

    Unhandled exception rendering component: The provided ContentType is not supported; the supported types are ‘application/json’ and the structured syntax suffix ‘application/+json’

    My current API output is: text/plain; charset=utf-8

    This was working with previous versions, but now it is not.

    • Daniel RothMicrosoft employee

      Hi Robert. I believe the current behavior is by design. The GetFromJsonAsync method expects the response content to be JSON. I’m not sure why it was working before for text/plain, but I don’t think that was the intent. If you think this scenario should be supported by System.Net.Http.Json, please file an issue on GitHub in the https://github.com/dotnet/runtime/issues repo.

      • Robert Leatherman

        Ok, thanks for the quick response. I’ll make the changes to my API to return the JSON content type. Strange it was working before.

  • Stefan Ossendorf

    Is it possible to re-use existing satellite assemblies for localization?
    We have a dedicated project for localization which we consume through nuget in our desktop applications. The

    IStringLocalizer{T}

    assumes I have resource files per razor page and is not picking up the provided assemblies.
    When I try to directly use the ResourceManager from our Nuget package I get a runtime error with the following description:

    Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
          Unhandled exception rendering component: Could not load type 'System.Resources.Extensions.DeserializingResourceReader' from assembly 'System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
    System.TypeLoadException: Could not load type 'System.Resources.Extensions.DeserializingResourceReader' from assembly 'System.Resources.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

    .
    The nuget package is a netstandard2.0/2.1 lib so it should work, right?

  • Erik Thysell

    Hi, I just started developing an app with blazor wasm + web api and I really like it. One thing on my wish list is a BLAS library/routines, especially vector-matrrix multiplications. In addition to thiis I would love to be able to use parallel execution!!!