January 28th, 2020

Blazor WebAssembly 3.2.0 Preview 1 release now available

Daniel Roth
Principal Product Manager

Today we released a new preview update for Blazor WebAssembly with a bunch of great new features and improvements.

Here’s what’s new in this release:

  • Version updated to 3.2
  • Simplified startup
  • Download size improvements
  • Support for .NET SignalR client

Get started

To get started with Blazor WebAssembly 3.2.0 Preview 1 install the .NET Core 3.1 SDK and then run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.2.0-preview1.20073.1

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.1.0 Preview 4 to 3.2.0 Preview 1:

  • Update all Microsoft.AspNetCore.Blazor.* package references to 3.2.0-preview1.20073.1.
  • In Program.cs in the Blazor WebAssembly client project replace BlazorWebAssemblyHost.CreateDefaultBuilder() with WebAssemblyHostBuilder.CreateDefault().
  • Replace IWebAssemblyHost with WebAssemblyHost.
  • Replace IWebAssemblyHostBuilder with WebAssemblyHostBuilder.
  • Move the root component registrations in the Blazor WebAssembly client project from Startup.Configure to Program.cs by calling builder.RootComponents.Add<TComponent>(string selector).
  • Move the configured services in the Blazor WebAssembly client project from Startup.ConfigureServices to Program.cs by adding services to the builder.Services collection.
  • Remove Startup.cs from the Blazor WebAssembly client project.
  • If you’re hosting Blazor WebAssembly with ASP.NET Core, in your Server project replace the call to app.UseClientSideBlazorFiles<Client.Startup>(...) with app.UseClientSideBlazorFiles<Client.Program>(...).

Version updated to 3.2

In this release we updated the versions of the Blazor WebAssembly packages to 3.2 to distinguish them from the recent .NET Core 3.1 Long Term Support (LTS) release. There is no corresponding .NET Core 3.2 release – the new 3.2 version applies only to Blazor WebAssembly. Blazor WebAssembly is currently based on .NET Core 3.1, but it doesn’t inherit the .NET Core 3.1 LTS status. Instead, the initial release of Blazor WebAssembly scheduled for May of this year will be a Current release, which “are supported for three months after a subsequent Current or LTS release” as described in the .NET Core support policy. The next planned release for Blazor WebAssembly after the 3.2 release in May will be with .NET 5. This means that once .NET 5 ships you’ll need to update your Blazor WebAssembly apps to .NET 5 to stay in support.

Simplified startup

We’ve simplified the startup and hosting APIs for Blazor WebAssembly in this release. Originally the startup and hosting APIs for Blazor WebAssembly were designed to mirror the patterns used by ASP.NET Core, but not all of the concepts were relevant. The updated APIs also enable some new scenarios.

Here’s what the new startup code in Program.cs looks like:

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("app");

        await builder.Build().RunAsync();
    }
}

Blazor WebAssembly apps now support async Main methods for the app entry point.

To a create a default host builder, call WebAssemblyHostBuilder.CreateDefault(). Root components and services are configured using the builder; a separate Startup class is no longer needed.

The following example adds a WeatherService so it’s available through dependency injection (DI):

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.Services.AddSingleton<WeatherService>();
        builder.RootComponents.Add<App>("app");

        await builder.Build().RunAsync();
    }
}

Once the host is built, you can access services from the root DI scope before any components have been rendered. This can be useful if you need to run some initialization logic before anything is rendered:

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.Services.AddSingleton<WeatherService>();
        builder.RootComponents.Add<App>("app");

        var host = builder.Build();

        var weatherService = host.Services.GetRequiredService<WeatherService>();
        await weatherService.InitializeWeatherAsync();

        await host.RunAsync();
    }
}

The host also now provides a central configuration instance for the app. The configuration isn’t populated with any data by default, but you can populate it as required in your app.

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.Services.AddSingleton<WeatherService>();
        builder.RootComponents.Add<App>("app");

        var host = builder.Build();

        var weatherService = host.Services.GetRequiredService<WeatherService>();
        await weatherService.InitializeWeatherAsync(host.Configuration["WeatherServiceUrl"]);

        await host.RunAsync();
    }
}

Download size improvements

Blazor WebAssembly apps run the .NET IL linker on every build to trim unused code from the app. In previous releases only the core framework libraries were trimmed. Starting with this release the Blazor framework assemblies are trimmed as well resulting in a modest size reduction of about 100 KB transferred. As before, if you ever need to turn off linking, add the <BlazorLinkOnBuild>false</BlazorLinkOnBuild> property to your project file.

Support for the .NET SignalR client

You can now use SignalR from your Blazor WebAssembly apps using the .NET SignalR client.

To give SignalR a try from your Blazor WebAssembly app:

  1. Create an ASP.NET Core hosted Blazor WebAssembly app.

    dotnet new blazorwasm -ho -o BlazorSignalRApp
    
  2. Add the ASP.NET Core SignalR Client package to the Client project.

    cd BlazorSignalRApp
    dotnet add Client package Microsoft.AspNetCore.SignalR.Client
    
  3. In the Server project, add the following Hub/ChatHub.cs class.

    using System.Threading.Tasks;
    using Microsoft.AspNetCore.SignalR;
    
    namespace BlazorSignalRApp.Server.Hubs
    {
        public class ChatHub : Hub
        {
            public async Task SendMessage(string user, string message)
            {
                await Clients.All.SendAsync("ReceiveMessage", user, message);
            }
        }
    }
    
  4. In the Server project, add the SignalR services in the Startup.ConfigureServices method.

    services.AddSignalR();
    
  5. Also add an endpoint for the ChatHub in Startup.Configure.

    .UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
        endpoints.MapHub<ChatHub>("/chatHub");
        endpoints.MapFallbackToClientSideBlazor<Client.Program>("index.html");
    });
    
  6. Update Pages/Index.razor in the Client project with the following markup.

    @using Microsoft.AspNetCore.SignalR.Client
    @page "/"
    @inject NavigationManager NavigationManager
    
    <div>
        <label for="userInput">User:</label>
        <input id="userInput" @bind="userInput" />
    </div>
    <div class="form-group">
        <label for="messageInput">Message:</label>
        <input id="messageInput" @bind="messageInput" />
    </div>
    <button @onclick="Send" disabled="@(!IsConnected)">Send Message</button>
    
    <hr />
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        HubConnection hubConnection;
        List<string> messages = new List<string>();
        string userInput;
        string messageInput;
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/chatHub"))
                .Build();
    
            hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
            {
                var encodedMsg = user + " says " + message;
                messages.Add(encodedMsg);
                StateHasChanged();
            });
    
            await hubConnection.StartAsync();
        }
    
        Task Send() => hubConnection.SendAsync("SendMessage", userInput, messageInput);
    
        public bool IsConnected => hubConnection.State == HubConnectionState.Connected;
    }
    
  7. Build and run the Server project

    cd Server
    dotnet run
    
  8. Open the app in two separate browser tabs to chat in real time over SignalR.

Known issues

Below is the list of known issues with this release that will get addressed in a future update.

  • Running a new ASP.NET Core hosted Blazor WebAssembly app from the command-line results in the warning: CSC : warning CS8034: Unable to load Analyzer assembly C:\Users\user\.nuget\packages\microsoft.aspnetcore.components.analyzers\3.1.0\analyzers\dotnet\cs\Microsoft.AspNetCore.Components.Analyzers.dll : Assembly with same name is already loaded.

    • Workaround: This warning can be ignored or suppressed using the <DisableImplicitComponentsAnalyzers>true</DisableImplicitComponentsAnalyzers> MSBuild property.

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!

Author

Daniel Roth
Principal Product Manager

Daniel Roth is a Program Manager on the ASP.NET team at Microsoft.

108 comments

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

  • Paul Roskilly

    With SignalR don’t you think there is any need to clean up / close the hubConnection when the component unloads?
    Say you navigate to another component and the navigate back back to the first one, does that mean a 2nd connection to the signal R hub is made and the first one is still in the background wasting resources?
    Although i can’t find a way of doing async things when a component disposes.

  • Piercarlo Schiavo - BIsolution

    Hi Daniel,

    I have a problem that "WebAssemblyHostBuilder" doesn´t load the appsettings.json configuration.

    I have the file "appsettings.json" in main directory of client side but the host.Configuration is every time empty.

    It would load "appsettings.json" as default like "IConfiguration" on server side or I need to do some other else ?

    Thank you for help

    <code>

    Read more
  • Hoffman, Scott M

    Is or will there be a migration document to migrate Blazor Server apps to Web Assembly?

      • Hoffman, Scott M

        Thank you!

        BTW, I really appreciate all the work that has been done to bring Blazor (both server side and web assembly) up to production support quality.

  • Fabian

    Hi Daniel,
    When it comes to sending a list of vehicles (car1, car2, train2, motocycle1) from the .net server to f.ex. Angular Client I used the capability of Newtonsoft.Json to add TypeNameHandling in order to indicate the type as a metadata to each Json object. Now as Newtonsoft.Json is not supported on Blazor Webassembly I wonder how to solve this?

    • Daniel RothMicrosoft employee Author

      Newtonsoft.Json should still work with Blazor WebAssembly. If you’re finding that’s not the case for your scenario, please let us know! Just file an issue on GitHub.

      • Fabian

        Pardon - you’re right of course.

        Let me seize the occasion to give you a feedback about my gratitude. Two things are very special in my opinion:

        First the fact that Microsoft being the world's biggest software developer achieved (despite its orientation for profitability) the change of ideology to turn its software development tools to open source. To me this is another revolution that Microsoft brought to the world and I am amazed how you manage to...

        Read more
  • Douglas Simao

    Just to understand... I created a Blazor client-side then I published it.
    it created a folder publish: Web App was published successfully file:///C:/BlazorApp1/bin/Release/netstandard2.1/publish/
    in there I got a lot of ddls: Microsoft.AspNetCore.Authorization.dll, Microsoft.Extensions.Configuration.Abstractions.dll etc also a file web.config and a folder BlazorApp1/dist with my files

    When I copied only the files from dist folder it didnt work, then when I copied everything from C:/BlazorApp1/bin/Release/netstandard2.1/publish/, ddls, web.config etc then it worked, also I did another test...

    Read more
    • Daniel RothMicrosoft employee Author

      Hi Douglas,

      The dist folder should have everything you need to run a standalone Blazor WebAssembly app. If you have an ASP.NET Core hosted Blazor WebAssembly app, then you’ll need everything in the publish folder. You can read all about how to publish Blazor WebAssembly apps here: https://docs.microsoft.com/aspnet/core/host-and-deploy/blazor/

  • Nemo

    Daniel, does the DOM diffing algorithm in StateHasChanged() take into account elements which are not visible and ignore them? E.g. if there is a table with 100 rows and columns, but if only the first 50 rows and 30 columns are visible, will DOM updates be pushed for the bottom 50 rows and 70 columns which are invisible? If the DOM diffing algorithm can track the visibility of elements and render accordingly, it would be...

    Read more
    • Daniel RothMicrosoft employee Author

      Hi Srihari,

      If by “visible” they mean “within the current scroll viewport” and “not hidden by CSS rules” then no, Blazor’s diffing algorithm doesn’t know about either of those. It wouldn’t be viable to create a diffing system that was somehow sensitive to those, since they can both change over time and then the prior diffing results would become incorrect. Blazor is concerned only with building the correct DOM contents, and then it’s a separate matter...

      Read more
  • Ismel Martínez Díaz

    Hello. Sorry if I don't understand well this web stack and what is the final goal of this new browser client technology. But I was expecting something different. I will write some questions, please give me some answers.

    Why is needed all the .net libraries (.dll)? I was expecting only one or two .wasm files. I think the C# code will be compiled to .wasm.

    Why is needed a server ? I think that I will do...

    Read more
    • Daniel RothMicrosoft employee Author

      Hi Ismel,

      Blazor WebAssembly apps work by including with the app a small .NET runtime implemented in WebAssembly. The .NET runtime is then used to execute normal .NET assemblies (.dlls) directly in the browser. This enables keeps build times fast and enables you to use existing .NET libraries in your app. We don't currently compile the entire app to WebAssembly. However, enabling support for compiling more of the app to WebAssembly is something we are working...

      Read more
      • Ismel Martínez Díaz

        Hi Daniel,

        Thanks for the answers, they are helpful.

        For the second answer, how I can generate the static files (which is the dist folder?), so I could take those files an put them under some other server?, for example, Python Flask lightweight web server.

        Best Regards, Ismel.

      • Daniel RothMicrosoft employee Author

        After doing a dotnet publish on your Blazor WebAssembly project the dist folder is located at /bin/Release/{TARGET FRAMEWORK}/publish/{ASSEMBLY NAME}/dist.

      • Ismel Martínez Díaz

        I will try it. Thanks a lot.

  • Chris Simeone

    Great post Dan, thanks!

    Can I create a Blazor WebAssembly app using Visual Studio for Mac (v8.4.6 build 36)?

    I installed .NET Core 3.1 SDK and the latest Blazor WebAssembly 3.2.0 Preview 1, but Blazor WebAssembly App template does not show up in Visual Studio for Mac.

    I also tried a CLI build, but get errors as well.

    For more detail about the problems I am having, here's my StackOverflow question:
    https://stackoverflow.com/questions/60324442/missing-blazor-webassembly-app-template-for-visual-studio-for-mac

    Read more
    • Daniel RothMicrosoft employee Author

      Hi Chris. Visual Studio for Mac currently doesn’t support creating Blazor WebAssembly projects. You can, however, use Visual Studio for Mac to create and develop Blazor Server projects. Support in Visual Studio for Mac for Blazor WebAssembly is planned for their upcoming 8.6 release.

  • JAHANGIR HUMMAYUN

    Hi Daniel,
    I have updated my existing project and changed Main method as you advised and given below. But i am getting an error that WebAssemblyHostBuilder is inaccessible due to its protection level.
    Can you please advise.

    Thanks

    • JAHANGIR HUMMAYUN

      Problem is resolved.

      • mohamed charif

        Could you tell me how you have resolved it?

      • Wil Wilder Apaza Bustamante

        this comment has been deleted.

  • Laxman Nagtilak

    Unable to find the _content folder in WebAssembly 3.2.0 Preview 1.
    I am using Blazored.Toast in my webassembly Project.
    I have referenced the css in index.html as below.

    <link href=”_content/Blazored.Toast/blazored-toast.css” rel=”stylesheet” />

    Before updating to WebAssembly 3.2.0 Preview 1 it was working but after updating the blazor to WebAssembly 3.2.0 Preview 1 it is not working .
    issue is Css file not found at the path.