As of Visual Studio 16.6.3 and .NET core 3.1.301 there’s now support for create Blazor applications for Server and WebAssembly.
Creating your project
From Visual Studio
- Create a new project and look for the Blazor App template
- You’ll be presented with the options to create a Blazor Server App or Blazor WebAssembly App
From the dotnet CLI
You can also run the generated code by changing directory to the your-app-name and then execute the following
dotnet run
Whichever route you took to generate your Blazor app. When you run the application, you can access the application via https://localhost:5001/.
Blazor Server
I’m not going to cover Blazor on the server specifically, as this is very much like Blazor WebAssembly crossed with ASP.NET core development. Basically what you write for WebAssembly is very much the same as you’d write for the Server.
There are benefits and downsides to Blazor Server and Blazor WebAssembly, I’m not going to list them all (because I’m sure I’ll forget one or two) but basically running Blazor on the server gives faster start-ups, allows us to be more secure with our source code (in that the code is not available to be downloaded but runs instead on the server). However the Server implementation suffers from the lack of an offline mode (i.e. PWA is supported via Visual Studio for Blazor WebAssembly) and there’s bound to be more network traffic with a server implementation.
Blazor WebAssembly
WebAssembly or WASM is a binary instruction set for browsers (well those that support it). Think of it as a virtual machine for running byte code. The important parts of WASM are that any it can run code generated from C# (other languages are adding support) instead of just using JavaScript for the Web. The second thing of interest is that the virtual machines are sandboxed.
It might sound like we’ve sort of been here before, and we have to a degree, but this time we have an open standard instead of plugins, Java applets, Silverlight or ActiveX.
With Blazor WebAssembly the compiled code is executed on the client, within the browser as a SPA. With Blazor Server, much like ASP.NET, the code comes from the server, however clever use of SignalR allows diffs to/from the DOM to be sent back and forth in an efficient manner.
Looking into the Blazor templates
If we look at both the WASM and Server code we’ll see our pages written in Razor syntax, here’s the Counter.razor file
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Razor syntax is denoted by the @ prefixed commands, for example @page is basically a routing command to this counter page. @code is a C# code block. Also we can use variables from our code by prefixing with the @ (such as @currentCount).
When you see a @code block, think of it as a class, hence in this example we have a field currentCount and a member method named IncrementCount.
Binding
One way binding is very simple (and shown in the above snippet)
<p>Current count: @currentCount</p>
In this case the variable is updated via the @code and one way binding ensures that the text in the HTML is updated automatically for us.
Ofcourse we’re going to need two-way binding and this is pretty simple in Blazor. Let’s add an input to the Counter.razor code (just place above the button HTML).
<input @bind="currentCount" />
This input will by default, bind the variable currentCount to it’s value property, we can also write explicit code for this in this way
<input @bind-value="currentCount" />
You use the syntax @bind-{Property} replacing {Property} with whatever the property or attribute name is that you wish to bind to.
What happens now is that, when the user changes the input value and the control loses focus, the currentCount is automatically set to the new value. We may want to instead have the value update as the input changes, in this instead we use @bind-value:event, for example
<input @bind-value="currentCount" @bind-value:event="oninput"/>
Note: if you put a char or string into the input, the binding doesn’t update and hence you get no exceptions or anything.
Blazor Components
Each page that we have is basically a Blazor component, but we can create a component that’s not a page – in other words it’s just a component and will be used to render HTML fragments.
From Visual Studio, right mouse click on the Shared folder and then select Add | Razor Component. Mine’s named Count.razor and the aim is to move the code into it’s own component
<p>Current count: @currentCount</p>
I called my component Count.razor. Let’s change the Counter.razor page to use this new component, so replace the code and above with
<Count @bind-Counter="currentCount"></Count>
Here’s our Count.razor component code
<p>Current count: @Counter</p>
@code {
[Parameter]
public int Counter { get; set; }
[Parameter]
public EventCallback<int> CounterChanged { get; set; }
}
Whilst we’re not using the CounterChanged event, it’s required for the binding code. The ParameterAttribute is basically exposing properties to the parent components or pages, i.e. for use outside of the component itself.
Now I’m not 100% on this code (i.e. CounterChanged not being used) as it worked fine, but I was finding Visual Studio displays error tildes under the currentCount usage in the Counter page, although everything worked. I’m not sure if this is just an issue where Visual Studio it not yet upto date with all the syntax or a mistake on my part – although it does work.
However, if we just change the page’s code to
<Count @bind-Counter="currentCount"
@bind-Counter:event="CounterChanged"></Count>
then no error tildes were displayed in Visual Studio – this needs further investigation as it seems a bit superfluous adding this event when it’s not used – but hey, I’m new to Blazor!
That’s it for Getting Started.
References
Razor syntax reference for ASP.NET Core
WebAssembly
Introduction to ASP.NET Core Blazor