Skip to content

Instantly share code, notes, and snippets.

@danroth27
Last active August 15, 2021 16:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danroth27/cc8290f0b16f34c1e1a478459790b83f to your computer and use it in GitHub Desktop.
Save danroth27/cc8290f0b16f34c1e1a478459790b83f to your computer and use it in GitHub Desktop.
Blazor

Get started building .NET web apps in the browser with Blazor

Blazor is an experimental web UI framework based on C#, Razor, and HTML that runs in the browser via WebAssembly. Blazor promises to greatly simplify the task of building fast and beautiful single-page applications that run in any browser. It does this by enabling developers to write .NET-based web apps that run client-side in web browsers using open web standards.

If you already use .NET, this completes the picture: you’ll be able to use your skills for browser-based development in addition to existing scenarios for server and cloud-based services, native mobile/desktop apps, and games. If you don’t yet use .NET, our hope is that the productivity and simplicity benefits of Blazor will be compelling enough that you will try it.

Why use .NET for browser apps?

Web development has improved in many ways over the years but building modern web applications still poses challenges. Using .NET in the browser offers many advantages that can help make web development easier and more productive:

  • Stable and consistent: .NET offers standard APIs, tools, and build infrastructure across all .NET platforms that are stable, feature rich, and easy to use.
  • Modern innovative languages: .NET languages like C# and F# make programming a joy and keep getting better with innovative new language features.
  • Industry leading tools: The Visual Studio product family provides a great .NET development experience on Windows, Linux, and macOS.
  • Fast and scalable: .NET has a long history of performance, reliability, and security for web development on the server. Using .NET as a full-stack solution makes it easier to build fast, reliable and secure applications.

How does it work?

Running .NET and C# in the browser is made possible by WebAssembly, a new web standard for a “portable, size- and load-time-efficient format suitable for compilation to the web.” WebAssembly enables fundamentally new ways to write web apps. Code compiled to WebAssembly can run in any browser at native speeds. Blazor runs on a WebAssembly based implementation of .NET. No plugins or transpilation needed.

Blazor apps are built out of components. Components are reusable pieces of web UI that handle events and maintain state. Blazor components are implemented using a combination of C# and HTML markup. At build-time your Blazor components are compiled into .NET classes that get downloaded into the browser as normal .NET assemblies (.dll).

When your app gets executed the components render their contents into a rendering tree that is used to update the browser DOM. Each time an event occurs on a component (ex in response to user interaction), that component regenerates its render tree. Blazor will then compare the new render tree against the previous one and apply any modifications to the browser DOM.

Let's get started!

Build your first Blazor app

To create your first project from Visual Studio:

  1. Select File -> New -> Project -> Web -> ASP.NET Core Web Application and click OK.

    New ASP.NET Core project

  2. The "New ASP.NET Core Web Application" dialog will appear. Make sure .NET Core and ASP.NET Core 2.0 are selected at the top. Pick the Blazor template and click OK.

    New Blazor app dialog

  3. Once the project is created, press Ctrl-F5 to run the app without the debugger. Running with the debugger (F5) is not supported at this time, but is coming soon.

Note: If you're not using Visual Studio you can install and use the Blazor templates from the command-line on your OS of choice (Windows, macOS, Linux):

dotnet new -i Microsoft.AspNetCore.Blazor.Templates
dotnet new blazor -o BlazorApp1
cd BlazorApp1
dotnet run

You should now be able to see your Blazor app running in the browser.

Blazor app home page

Building components

Now let's take a look at how you build web UI components with Blazor.

  1. Browse to each of the app's three pages: Home, Counter, Fetch data.

    These three pages are implemented by the three Razor files in the Pages folder: Index.cshtml, Counter.cshtml, FetchData.cshtml. Expand the Pages folder in the Solution explorer to see these files. Each of these files implements a Blazor component that will get compiled and executed client-side in the browser.

    Pages folder

  2. Try clicking the button on the Counter page.

    Blazor app home page

    Each click increments the counter without a page refresh. Normally this kind of client-side behavior would be handled in JavaScript, but here it's implemented in C# and .NET by the Counter component.

  3. Take a look at the implementation of the Counter component in the Counter.cshtml file:

    @page "/counter"
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button @onclick(IncrementCount)>Click me</button>
    
    @functions {
        int currentCount = 0;
    
        void IncrementCount()
        {
            currentCount++;
        }
    }

    The UI for the Counter component is defined using normal HTML. Dynamic rendering logic (loops, conditionals, expressions, etc.) is added using an embedded C# syntax called Razor. The HTML markup and C# rendering logic are converted into a component class at build time. The name of the generated .NET class matches the name of the file.

    Members of the component class are defined in a @functions block. In the @functions block you can specify component state (properties, fields) as well as methods for event handling or for defining other component logic. These members can then be used as part of the component's rendering logic and for handling events.

    When the button is clicked the counter component's registered onclick handler is called (the IncrementCount method) and the Counter component regenerates its render tree. Blazor will then compare the new render tree against the previous one and apply any modifications to the browser DOM. In the case of the counter component the displayed count gets updated.

  4. Update the markup for the Counter component to make the top level header more exciting!!.

    @page "/counter"
    <h1><em>Counter!!</em></h1>
  5. Also modify the C# logic of the Counter component to make the count increment by two instead of one.

    @functions {
        int currentCount = 0;
    
        void IncrementCount()
        {
            currentCount += 2;
        }
    }
  6. Build and rerun the app by from within Visual Studio by pressing Ctrl-F5 to see the changes (live reload support coming soon).

    Exciting counter

Using components

Once you define a component it can be used to implement other components. The markup for using a component looks like an HTML tag where the name of the tag is the component type.

  1. Add a Counter component to the home page of the app, like this:

    @page "/"
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <SurveyPrompt Title="How is Blazor working for you?" />
    
    <Counter />
  2. Build and run the app (Ctrl-F5). You should now see a separate instance of the Counter component on the home page.

    Blazor home page with counter

Component parameters

Components can also have parameters, which you define using public properties on the component class. Use attributes to specify arguments for a component in markup.

  1. Update the Counter component to have an IncrementAmount property that defaults to 1, but that we can change to something different.

    @functions {
        int currentCount = 0;
    
        public int IncrementAmount { get; set; } = 1;
    
        void IncrementCount()
        {
            currentCount += IncrementAmount;
        }
    }
  2. On the home page change the increment amount for the Counter to 10.

    <Counter IncrementAmount="10" />
  3. Build and run the app (Ctrl-F5)

    The counter on the home page now increments by 10, while the counter page still increments by 1.

    Blazor count by ten

Routing to components

The @page directive at the top of the Counter.cshtml file specifies that this component is a page to which requests can be routed. Specifically, the Counter component will handle requests sent to /counter. Without the @page directive the component would not handle any routed request, but it could still be used by other components.

Dependency injection

Services registered with the app's service provider are available to components via dependency injection. You can inject services into a component using the @inject directive.

Take a look at the implementation of the FetchData component in FetchData.cshtml. The @inject directive is used to inject an HttpClient instance into the component.

@page "/fetchdata"
@inject HttpClient Http

The FetchData component uses the injected HttpClient to retrieve some JSON from the server when the component is initialized. Under the covers the HttpClient provided by the Blazor runtime is implemented using JavaScript interop to call the underlying browser fetch API to send the request (it is possible from C# to call any JavaScript library or browser API). The retrieved data is deserialized into the forecasts C# variable as an array of WeatherForecast objects.

@functions {
    WeatherForecast[] forecasts;

    protected override async Task OnInitAsync()
    {
        forecasts = await Http.GetJsonAsync<WeatherForecast[]>("/sample-data/weather.json");
    }

    class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF { get; set; }
        public string Summary { get; set; }
    }
}

A @foreach loop is then used to render each forecast instance as a row in the weather table.

<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>

Build a todo list

Let's add a new page to our app that implements a simple todo list.

  1. Add a Todo page to the app by right-clicking on the Pages folder and selecting Add -> New item -> Razor View. Name the file Todo.cshtml and click OK. Add Razor View

  2. Replace the content of the Todo.cshtml file with some initial markup.

    @page "/todo"
    
    <h1>Todo</h1>
  3. Add the todo list page to the nav bar by updating Shared/NavMenu.cshtml to add a nav link for the todo list. Add the following list item markup below the existing ones.

    <li>
        <NavLink href="/todo">
            <span class='glyphicon glyphicon-th-list'></span> Todo
        </NavLink>
    </li>
  4. Build and run the app. You should now see the new todo page.

    Blazor todo start

  5. Add a class to represent your todo items by right-clicking on the project and selecting Add -> Class. Name the file TodoItem.cs and click OK.

    Add new class Add TodoItem.cs

  6. Replace the class definition in TodoItem.cs with the following class.

    public class TodoItem
    {
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
  7. Now go back to the Todo component in Todo.cshtml and add a field for the todos in a @functions block. The Todo component will use this field to maintain the state of the todo list.

    @functions {
        IList<TodoItem> todos = new List<TodoItem>();
    }
  8. Add some list markup and a foreach loop to render each todo item as a list item.

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
  9. Now we need some UI for adding todos to the list. Add a text input and a button at the bottom of the list.

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" />
    <button>Add todo</button>
    
    @functions {
        IList<TodoItem> todos = new List<TodoItem>();
    }
  10. Build and run the app (Ctrl-F5)

    Add todo button Nothing happens yet when we click the "Add todo" button, because we haven't wired up an event handler.

  11. Add an AddTodo method to the Todo component and register it for button clicks using the @onclick attribute.

    <input placeholder="Something todo" />
    <button @onclick(AddTodo)>Add todo</button>
    
    @functions {
        IList<TodoItem> todos = new List<TodoItem>();
    
        void AddTodo()
        {
            // Todo: Add the todo
        }
    }

    The AddTodo C# method will now get called every time the button is clicked.

  12. To get the title of the new todo item add a newTodo string field and bind it to the value of the text input using the @bind attribute.

    IList<TodoItem> todos = new List<TodoItem>();
    string newTodo;
    <input placeholder="Something todo" @bind(newTodo) />
  13. We can now update the AddTodo method to add the TodoItem with the specified title to the list. Don't forget to clear the value of the text input by setting newTodo to an empty string.

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind(newTodo) />
    <button @onclick(AddTodo)>Add todo</button>
    
    @functions {
        IList<TodoItem> todos = new List<TodoItem>();
        string newTodo;
    
        void AddTodo()
        {
            if (!String.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = "";
            }
        }
    }
  14. Build and run the app (Ctrl-F5). Try adding some todos to your todo list.

    Add todos

  15. Lastly, what's a todo list without check boxes? And while we're at it we can make the title text for each todo item editable as well. Add a checkbox input and text input for each todo item and bind their values to the Title and IsDone properties respectively.

    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind(todo.IsDone) />
                <input @bind(todo.Title) />
            </li>
        }
    </ul>
  16. To verify that these values are being bound, update the h1 header to show a count of the number of todo items that are not yet done.

    <h1>Todo (@todos.Where(todo => !todo.IsDone).Count())</h1>
  17. Your completed Todo component should look like this:

    @page "/todo"
    
    <h1>Todo (@todos.Where(todo => !todo.IsDone).Count())</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind(todo.IsDone) />
                <input @bind(todo.Title) />
            </li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind(newTodo) />
    <button @onclick(AddTodo)>Add todo</button>
    
    @functions {
        IList<TodoItem> todos = new List<TodoItem>();
        string newTodo;
    
        void AddTodo()
        {
            if (!String.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = "";
            }
        }
    }

Build and run the app and try adding some todo items.

Finished Blazor todo list

Publishing and deployment

Now let's publish our Blazor app to Azure.

  1. Right click on the project and select Publish.

    Publish

  2. In the "Pick a publish target" dialog select "App Service" and "Create New", then click Publish.

    Pick a publish target

  3. In the "Create App Service" dialog pick a name for the application and select the subscription, resource group, and hosting plan that you want to use. Click "Create" to create the app service and publish the app.

    Create app service

Wait a minute or so for the app to be deployed.

Your app should now be running in Azure.

Blazor on Azure

You can mark that todo item to build your first Blazor app as done. Nice job!

Additional resources

For a more involved Blazor sample app check out the Flight Finder sample on GitHub.

Blazor Flight Finder

Summary

This is the first preview release of Blazor. Already you can get started building component-based web apps that run in the browser with .NET. We invite you to try out Blazor today and let us know what you think about the experience so far. Check out https://aka.ms/install-blazor to get started. You can file issues on Github, take our in-product survey, and chat with us on Gitter. But this is just the beginning! We have many new features and improvements planned for future updates. We hope you enjoy trying out this initial release and we look forward to sharing new improvements with you in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment