A gentle introduction to Blazor Server

March 8, 2019 · 6 minute read · Tags: blazor

Note: Razor Components is now called Blazor Server. Bear that in mind as you read on!

Psst have you heard about Razor Components?

They’re new, a bit weird when you first see them and they may or may not change how we’re all building ASP.NET web applications in the next few years.

Given they’re due to land with ASP.NET Core 3 (which is now just around the corner) I figured I’d take them for a spin and document the results here.

Caveat: What follows is correct as of ASP.NET Core 3 Preview 3, this stuff changes fast so may become inaccurate in the future!

What on earth are Razor Components?

If you grab the latest Visual Studio 2019 preview and the .NET Core 3 Preview 3 (or higher), you’ll get a new “Razor Components” option when you create a new ASP.NET Core web application.

Go ahead and select that and you’ll find yourself looking at a project structure like this one…

Take a look in Components/Pages and you’ll see some weird looking .razor files.

And here’s the code for counter.razor.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

So what is this madness?

You’re looking at a new paradigm for building client (web) applications without requiring javascript.

That’s right, everyone got fed up of all the new javascript frameworks (and ecosystem) so Microsoft created one that doesn’t even require you to use javascript! 😛

Unleash Blazor's Potential

Blazor promises to make it much easier (and faster) to build modern, responsive web applications, using the tools you already know and understand.

Subscribe to my Practical ASP.NET Blazor newsletter and get instant access to the vault.

In there you'll find step-by-step tutorials, source code and videos to help you get up and running using Blazor's component model.

I respect your email privacy. Unsubscribe with one click.

    Here’s how I understand it to work.

    Your Razor Components application runs on the server. When you make a request (in the browser) to view a page, ASP.NET core attempts to locate the relevant Razor Component.

    In this case /counter would route to our Counter component because of this line.

    @page "/counter"
    

    ASP.NET then generates an initial version of your page as static HTML and sends this back to the browser.

    Your browser renders this static page first before doing the funky bit, which is to open up a socket connection back to your server (using SignalR).

    From here on in, when you interact with the component (in this case, by clicking the button) it uses that socket connection to ping events (e.g. mouse click) over to the server.

    Your code then runs (IncrementCounter) and if it changes the UI in any way (in this case incrementing the counter, the current value of which is shown in a <p> tag) the HTML that’s changed (the DOM) is sent back to the browser (via the socket connection) and that part of the page is re-rendered.

    Weird huh?

    What’s the point?

    So technically this is an interesting new way to build client-side applications.

    You’re essentially building your app server-side, but are able to adopt Razor Component’s model for your UI.

    It’s the component model which is interesting and makes this closer to something like React than ASP.NET MVC.

    As with React (and Angular for that matter) you can create small components, where they key UI logic (events, model/DOM changes) is contained within the component, then compose your user interface using those components.

    You are also able to interact with your back-end services directly as part of this process, without the usual javascript > AJAX > Web API combination.

    Here’s how the example FetchData page works.

    @page "/fetchdata"
    @using WebApplication11.Services
    @inject WeatherForecastService ForecastService
    
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
    
    @functions {
        WeatherForecast[] forecasts;
    
        protected override async Task OnInitAsync()
        {
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        }
    }
    

    See that bit at the end, where it calls a ForecastService to get the forecasts and assign them to forecasts? That’s where a javascript app would need to make an AJAX call.

    But with Razor Components, because this code actually executes server-side, no AJAX call is required, you can just call the method directly.

    When you do, the forecasts property is updated and the Razor markup ensures the UI shows the latest data (loops through each forecast and renders a row for each one).

    Now say you had a button to refresh those forecasts.

    <button onclick="@Refresh">Refresh</button>
    
    // rest of markup here
    
    @functions {
        WeatherForecast[] forecasts;
    
        // other functions
    
        async Task Refresh()
        {
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        }
    }
    

    When the button is clicked that event will be sent back to the server via the open SignalR connection.

    The Refresh method will then be invoked (on the server).

    The data will be retrieved, the forecasts property updated and the resulting DOM changes pushed back to the browser via the socket connection.

    What about Blazor?

    You’ve heard about Blazor? It uses the exact same model we’ve explored here, except instead of running in the server, the code runs in something called Web Assembly, in the browser.

    This enables the browser to run your .NET application directly, meaning all events raised would be handled in the browser and not sent back to a server.

    Unlike Razor Components, because Blazor runs in the browser, accessing data (e.g. from a database) requires AJAX calls back to a server (likely Web API) to get data. So in this sense much more like the javascript applications we know and love/hate.

    Worth noting that Blazor is still experimental and depends very much on the .NET runtime for Web Assembly becoming fast enough to be a viable choice whereas Razor Components is shipping with .NET Core 3.

    Interesting stuff, what next?

    As I started to wrap my head around Razor Components I became curious how components can communicate with other components, and how to build a feature made up of 2 or more components.

    That’s what we’ll explore in part 2.

    Unleash Blazor's Potential

    Blazor promises to make it much easier (and faster) to build modern, responsive web applications, using the tools you already know and understand.

    Subscribe to my Practical ASP.NET Blazor newsletter and get instant access to the vault.

    In there you'll find step-by-step tutorials, source code and videos to help you get up and running using Blazor's component model.

    I respect your email privacy. Unsubscribe with one click.

      Next up

      The quickest way to integrate PayPal checkout with Blazor SSR in .NET 8
      JavaScript Interop works differently with Blazor Server-side rendering
      Interactive what now? Deciphering Blazor’s web app project template options
      Create a new Blazor Web App and you’ll be asked how you want interactivity to work, but what does it all mean?
      Should I put my Blazor components in the server project, or the client project?
      .NET 8 gives you a choice of projects, which one should you use?