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()
withWebAssemblyHostBuilder.CreateDefault()
. - Replace
IWebAssemblyHost
withWebAssemblyHost
. - Replace
IWebAssemblyHostBuilder
withWebAssemblyHostBuilder
. - Move the root component registrations in the Blazor WebAssembly client project from
Startup.Configure
to Program.cs by callingbuilder.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 thebuilder.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>(...)
withapp.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:
-
Create an ASP.NET Core hosted Blazor WebAssembly app.
dotnet new blazorwasm -ho -o BlazorSignalRApp
-
Add the ASP.NET Core SignalR Client package to the Client project.
cd BlazorSignalRApp dotnet add Client package Microsoft.AspNetCore.SignalR.Client
-
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); } } }
-
In the Server project, add the SignalR services in the
Startup.ConfigureServices
method.services.AddSignalR();
-
Also add an endpoint for the
ChatHub
inStartup.Configure
..UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); endpoints.MapHub<ChatHub>("/chatHub"); endpoints.MapFallbackToClientSideBlazor<Client.Program>("index.html"); });
-
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; }
-
Build and run the Server project
cd Server dotnet run
-
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.
- Workaround: This warning can be ignored or suppressed using the
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!
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.
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>
Is or will there be a migration document to migrate Blazor Server apps to Web Assembly?
We don’t have a doc for this yet, but we should! I filed https://github.com/dotnet/AspNetCore.Docs/issues/17294 to track this feedback.
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.
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?
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.
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...
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...
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/
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...
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...
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...
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...
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.
After doing a
dotnet publish
on your Blazor WebAssembly project the dist folder is located at /bin/Release/{TARGET FRAMEWORK}/publish/{ASSEMBLY NAME}/dist.I will try it. Thanks a lot.
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
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.
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
Problem is resolved.
Could you tell me how you have resolved it?
this comment has been deleted.
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.
It looks like you’re already following up with the Blazored.Toast folks on this one: https://github.com/Blazored/Toast/issues/51. If this turns out to be a Blazor WebAssembly issue please let us know by filing an issue at https://github.com/dotnet/aspnetcore/issues.