How to debug a Blazor project

Why is debugging Blazor applications different from Angular or React?

When you run a JavaScript framework, like Angular or React, the JavaScript code is available on the client-side. This makes it possible to use the built-in developer tools in the browser to inspect and step through the code. When running Blazor applications you execute a .NET runtime that runs your compiled C# code, a totally different story.

The first thing to realize is that you will not be able to use the regular developer tools, since they only support JavaScript at this time. A second ”aha” moment comes when you realize that you need to have your application compiled in debug mode in order to have debugging symbols available.

But if the built in developer tools does not support Blazor, what to use?

Current support

At this time there is only very early support for debugging client-side Blazor applications. And the only browser where debugging is supported is in Chrome.

The reason only Chrome is supported at this time is because Blazor provides a debugging proxy that implements the Chrome DevTools Protocol. This allows the DevTools in Chrome to talk to the proxy, which in turn connects to your running Blazor application. In order for the proxy to be able to connect to the running application, remote debugging must be enabled in Chrome. It’s a bit cumbersome, but I will go through the steps required in detail below.

Hopefully the Blazor team will focus on improving the debugging support since it is a very important ingredient if Blazor is to be popular among developers.

Debugging – step-by-step guide

Follow these steps and you will have a debugging session up and running in no time. I will assume you have Chrome installed and a working Blazor application that you wish to debug.

  1. Open up the application in Visual Studio (I was unable to start the debugging session when started on the command line)
  2. Ensure that Visual Studio is set up for building the application in Debug mode and the target browser is set to Chrome (see image below)
  3. Press F5 to start the application and it should open up Chrome and load it
  4. Press Shift+Alt+D (I use Dvorak keyboard layout where the QWERTY layout D is mapped to the letter E, so I had to press Shift+Alt+E)
  5. Chrome will open a new tab, showing an error message that it wasn’t started with remote debugging enabled
  6. Follow the instructions in the error message (close Chrome, then restart it using Win+R and paste a command similar to ”%programfiles(x86)%\Google\Chrome\Application\chrome.exe” –remote-debugging-port=9222 http://localhost:54308/)
  7. In the new Chrome window, press Shift+Alt+D again
  8. A new tab should open in Chrome showing the remote debug utils
  9. You should be able to find a heading named ”Sources” (see image below) where you find the Blazor DLL and under that the source files
  10. Add breakpoints and switch back to the other tab to interact with the application. Once a breakpoint is hit Chrome will display a message saying that the application is paused since it is stopped at a breakpoint

Figure 1. Visual Studio set up for debugging the Blazor application

Figure 2. Debugging the Blazor application in Chrome

Limitations

Remember that I wrote that debugging support is still in a very early stage. This means that there are a lot of things that are not supported in the debugger yet. Limitations include, but may not be limited to:

  • No support for stepping into child methods
  • Values of locals of other types than int, string, and bool cannot be inspected
  • Values of class properties and fields cannot be inspected
  • It is not possible to see values of variables by hoovering over them
  • Expressions cannot be evaluated in the console

Ending words

As you understand by now there is still a lot of work to do in order to get full debugging support with Blazor, but the fact that there are some debugging support in place is promising. It is a bit cumbersome to start a debug session, but it is not hard. I have worked in really large projects with custom build tools without a working debugger and it is not a good spot to be in. However, with Blazor I have good hopes that the development team understands the importance of a good debugger.

How to consume a REST API using Blazor

The RESTful service

A couple of blog posts ago I wrote about how to design a REST API with ASP.NET Core and now I intend to show how to create a front end that can interface this service in order to create and remove products from the repository.

To recap, the RESTful service was designed to manage a repository containing Products where a Product is defined like this:

public class Product
{
  public long Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
}

And the API to manage the Products looks like this:

URI Operation Description
/products GET Lists all the products
/products/{id} GET Returns information about a specific product
/products POST Creates a new product
/products/{id} PUT Replaces an existing product
/products/{id} DELETE Deletes a product

I will create an application, using Blazor, that can be used to list all products, create a new product, and delete an existing product.

Creating the Blazor application

Start by creating a new Blazor application. If you’ve never done this before there are some components that you need to install, follow the instruction on https://blazor.net/docs/get-started.html for details on how to do this.

Once you have all dependencies in place run the following command:

dotnet new blazor -o ProductsManager

which will create a new Blazor project named ProductsManager.

You can test that it works by changing directory to the new ProductsManager directory and running the application:

cd ProductsManager

dotnet run

You should now be able to open your web browser and see you Blazor application in action.

 

Notice the Fetch data link. Clicking this loads the FetchData component which we now will modify to fetch data via our REST API.

Fetching our Data

Open the ProductsManager project file in Visual Studio. A solution will be created automatically for you.

In the Pages folder you will find the FetchData component. If you open the source file (FetchData.cshtml) and scroll to the bottom you will find a call to HttpClient.GetJsonAsync that currently just reads a sample file located in wwwroot/sample-data.

The first thing we do is to replace the weather.json file with products.json in the wwwroot/sample-date/ and enter some sample data. Rename the weather.json file to products.json and replace the content with the following:

[
  {
    "Id": 1,
    "Name": "Unsteady chair",
    "Description":  "Chess player's secret weapon"
  },
  {
    "Id": 2,
    "Name": "Weather controller",
    "Description": "Control the weather with a simple click of a button. Requires two AA batteries (not included)"
  }
]

Now you will also need to update the FetchData component. Change the WeatherForecast class to look like the Product class above and update all related code to match these changes. The updated file is listed below:

@page "/fetchdata"
@inject HttpClient Http

<h1>Products listing</h1>

@if (products == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var product in products)
            {
                <tr>
                    <td>@product.Id</td>
                    <td>@product.Name</td>
                    <td>@product.Description</td>
                </tr>
            }
        </tbody>
    </table>
}

@functions {
    Product[] products;

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

    class Product
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
}

Now, if everything works as expected you should be able to see the product listing from the sample file instead of the Weather Forecast when you click the Fetch Data link in your browser.

To get the data from an external web service via a REST API you simply need to change the ”sample-data/products.json” string to the URL of the web service. In my test I ran the server on localhost on port 44359. So when testing I added a const string:

private const string APIServer = "https://localhost:44359/api/products";

and then just changed the OnInitAsync method to look like this:

protected override async Task OnInitAsync()
{
  products = await Http.GetJsonAsync<Product[]>(APIServer);
}

Important: If you get access denied errors you need to ensure that you have set up Cross-Origin Resource Sharing (CORS) correctly in the RESTful service. You can read about how to do that here: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1

Once you have that working it should be quite straight forward how to extend the FetchData component to be able to add and remove products by using the REST API. Below I have a code listing of my working component:

@page "/fetchdata"
@inject HttpClient Http

<h1>Interfacing the Products API</h1>

@if (products == null)
{
  <em>Loading...</em>
}
else
{
  <table class="table">      
  <thead>          
  <tr>
    <th>Id</th> 
    <th>Name</th>            
    <th>Description</th>            
    <th></th>
  </tr>
  </thead>      
  <tbody>
  @foreach (var product in products)
  {              
    <tr>
      <td>@product.Id</td>
      <td>@product.Name</td>              
      <td>@product.Description</td>
      <td><input type="button" value="Delete" onclick="@(async () => await Delete(product.Id))" /></td>
    </tr>
  }
  </tbody>
  </table>

  <h2>Add a new product</h2>
  <form>
  <table>
  <tr>
    <td><label>Name</label></td>              
    <td><input type="text" bind="@Name" /></td>
  </tr>
  <tr>
    <td><label>Description</label></td>
    <td><input type="text" bind="@Description" /></td>
  </tr>
  <tr>
    <td></td>              
    <td><input type="button" value="Add" onclick="@(async () => await Add())" /></td>
  </tr>
  </table>
  </form>
}

@functions {
    private const string APIServer = "https://localhost:44359/api/products";

    private Product[] products;

    private string Name { get; set; } = "";
    private string Description { get; set; } = "";

    protected override async Task OnInitAsync()
    {
        products = await Http.GetJsonAsync<Product[]>(APIServer);
    }

    private async Task Add()
    {
        var newProduct = new Product { Name = Name, Description = Description };
        Name = string.Empty;
        Description = string.Empty;
        await Http.SendJsonAsync(HttpMethod.Post, APIServer, newProduct);
        products = await Http.GetJsonAsync<Product[]>(APIServer);
    }

    private async Task Delete(long productId)
    {
        await Http.DeleteAsync(APIServer + "/" + productId);
        products = await Http.GetJsonAsync<Product[]>(APIServer);
    }

    private class Product
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
}

I hope you found this at least a bit helpful. If anything is unclear just add a comment. And If you want me to publish the code on GitHub just let me know and I will do that as well.

Blazor – first impressions

What is Blazor?

To quote the official Blazor homepage

”Blazor is a single-page web app framework built on .NET that runs in the browser with WebAssembly.”

The natural follow-up question is then ”What is WebAssembly?”. From the official WebAssembly homepage we can read that

”WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.”

That is a very technical description, most likely formulated by a software engineer. I will make an attempt to describe Blazor and WebAssembly in my own words.

Blazor is a framework for building applications for the web, similar to AngularJS and React. However, Blazor makes it possible to write your applications in a .NET language, such as C#, instead of JavaScript. Since the JavaScript engines in the browsers are limited to executing JavaScript another solution is required for running compiled programs in binary format. This new format is called WebAssembly, Wasm, and is supported by Chrome, Edge, Firefox, and Safari.

Part of the Blazor project is to create a .NET Runtime in the Wasm format that runs in the browser and executes .NET bytecode.

Why Blazor over AngularJS or React?

Currently Blazor is still experimental so you should not use it in live products, yet. However, when it reaches a more stable state it should make a pretty awesome alternative to the JavaScript based frameworks. If you already write your Middleware and Backend code using .NET or .NET Core than it should be appealing to be able to use C# for the front-end as well, being able to go full stack using C#.

Another big thing is that compiled binary code in WebAssembly executes up to 5-10 times faster than JavaScript. In a time where JavaScript performance is becoming a bottleneck for web applications this is major deal.

Then there are a bunch of other things that makes it appealing to run .NET in the browser, like great development tools, well known APIs and stable build tools.

How is it to develop with Blazor right now?

I set up Blazor and went through a couple of tutorials and I must say that it feels really stable and performant already, even though it is still at an experimental stage. Being a .NET developer spending most of my time writing code in C# it felt really nice to be able to use that instead of JavaScript. Even though JavaScript is perfectly fine and I have nothing against developing in JavaScript if the job requires it, I feel a lot more comfortable with C# so it’s nice to be able to write both the backend code and the frontend code using C#.

When you create your web application with Blazor you create components which are HTML and C# code that you can either choose to display separately or as part of other components. The concept is easy to grasp and if you are comfortable working with HTML and C# you should be able to understand what’s going on in the code right away.

If you are a C# developer interested in web development I highly recommend that you give Blazor a try. My guess is that it will become one of the major web frameworks for creating Single Page Applications (SPA).

How can I get started?

Visit the official Blazor web site at https://blazor.net where you will find instructions on how to get started as well as a tutorial that will guide you through the basic concepts.

You may also want to visit the official WebAssembly homepage at https://webassembly.org to learn more about Wasm.

How to design a REST API with C# in ASP.NET Core 2

What is REST?

REST is short for Representational State Transfer,  and is way to design web services. So called RESTful web services.

Usually the RESTful service is accessible via a URI and HTTP operations such as  GET, POST, PUT, and DELETE are used to get or modify the data that is often stored in a database behind the web service.

Data being retrieved or sent to the web service is often formatted as JavaScript Object Notation, JSON.

Defining the API

Let’s assume we have a database containing Products that we wish to be able to Create, Read, Update, and Delete (CRUD) using the API. The service that handles the requests will be accessed using HTTP operations as listed below:

URI Operation Description
/products GET Lists all the products
/products/{id} GET Returns information about a specific product
/products POST Creates a new product
/products/{id} PUT Replaces an existing product
/products/{id} DELETE Deletes a product

Note that it does not matter whether the client that will be using the API is a mobile app, a desktop app, a web app, or something else.

Creating the RESTful Service

I am using Visual Studio 2017, Version 15.8.5 and .NET Core 2.1. If you use different versions, things may work a little different.

Start by selecting File -> New -> Project and in the ”New Project” dialog box choose Visual C# -> Web -> ASP.NET Core Web Application. Name the project ”ProductsAPI” and click OK.

 

In the next dialog that pops up, select ’API’ and click OK.

When you use this template, code will be generated that sets up some basic configuration and adds a dummy controller so that you can build and run the application. If you press ’Ctrl + F5’ the application should start and open up a new browser tab displaying ”value1” and ”value2” formatted as JSON.

Implementing the API

Creating a Product model

Let’s start by adding a Product model. Looking at the API definition above we can see that we want the Product to have an Id. It should also have a Name and a Description, so let’s add that as well:

public class Product
{
  public long Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
}

I created a Models folder on project level and added the Product class there.

Creating a ProductContext and a DbSet

Since we are using ASP.NET I want to take advantage of Entity Framework when working with the database. Entity Framework is an Object-Relational Mapper (O/RM) which let’s you work with domain specific objects and don’t have to worry so much about how to interface with the database. The Entity Framework types that we will be using are the DbContext and the DbSet. The DbContext represents the connection to the database and one or more tables. The tables are represented by DbSets.

Confusing? Let’s look at some code:

public class ProductContext : DbContext
{
  public DbSet<Product> Products { get; set; }

  public ProductContext(DbContextOptions<ProductContext> options) : base(options)
  {
  }
}

The code above informs us that we expect to have a database containing a table of Products. The constructor argument is of type DbContextOptions and will contain configuration options for the database connection.

Registering the ProductContext with the Dependency Injection container

In order to make it easy to be able to query and update the database I will register the ProductContext with the Dependency Injection container which is a built in component of ASP.NET Core. Doing that will make it possible to automatically instantiate objects that takes a ProductContext as a constructor parameter. I will use that later on when designing the ProductsController.

When the project was generated from the API template one of the files that were automatically added and populated was the Startup.cs. This class contains a couple of methods that gets called by the runtime during application startup. We will register the ProductContext in the ConfigureServices method by adding this line of code:

services.AddDbContext<ProductContext>(options => options.UseInMemoryDatabase("ProductList"));

This single line registers the ProductContext as a service in the Dependency Injection service collection and specifies an in memory database, named ProductList to be injected into the service container. Not bad for a single line of code, don’t you think?

Creating a controller to handle the HTTP requests

So far we have only created scaffolding, but no implementation to actually handle any HTTP requests. Now it’s time to change that.

Looking back at the API definition we expect that a user should be able to list all the products in the database by a GET request using the URI /products. The most straightforward way to accomplish this is to add a ProductsController, that takes a ProductContext in it’s constructor, and then add a Get action that returns the list of products.

There should be a folder in the projects that is named Controllers. Add a new API Controller to it and name it ProductsController. The code should look like this:

[Route("api/[controller]"]
[ApiController]
public class ProductsController : ControllerBase
{
  private readonly ProductContext _context;
  public ProductsController(ProductContext context)
  {
    _context = context;
    if (_context.Products.Count() == 0)
    {
      _context.Add(new Product
      {
        Name = "Ford Mustang",
        Description = "Classic American car."
      });
      _context.SaveChanges();
    }
  }

  [HttpGet]
  public ActionResult<IEnumerable<Product>> GetAll()
  {
    return _context.Products.ToList();
  }
}

As you can see, I add a new Product, a Ford Mustang, in the case that the database is empty. This is just so that we can see that it works as expected.

Pressing Ctrl+F5 and browsing to http://localhost:<some_port>/api/products should now result in something similar to this:

Implementing the rest of the API is pretty similar. I will just throw the code right at you:

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
  private readonly ProductContext _context;

  public ProductsController(ProductContext context)
  {
    _context = context;
    if (_context.Products.Count() == 0)
    {
      _context.Add(new Product
      {
        Name = "Ford Mustang",
        Description = "Classic American car."
      });
      _context.SaveChanges();
    }
  }

  [HttpGet]
  public ActionResult<IEnumerable<Product>> GetAll()
  {
    return _context.Products.ToList();
  }

  [HttpGet("{id}", Name = "GetProduct")]
  public ActionResult<Product> GetById(long id)
  {
    var p = _context.Products.Find(id);
    if (p == null)
    {
      return NotFound();
    }
    return p;
  }

  [HttpPost]
  public IActionResult Create(Product product)
  {
    _context.Products.Add(product);
    _context.SaveChanges();

    return CreatedAtRoute("GetProduct", new { id = product.Id }, product);
  }

  [HttpPut("{id}")]
  public IActionResult Update(long id, Product product)
  {
    var p = _context.Products.Find(id);
    if (p == null)
    {
      return NotFound();
    }
    p.Name = product.Name;
    p.Description = product.Description;

    _context.Products.Update(p);
    _context.SaveChanges();

    return NoContent();
  }

  [HttpDelete("{id}")]
  public IActionResult Delete(long id)
  {
    var p = _context.Products.Find(id);
    if (p == null)
    {
      return NotFound();
    }

    _context.Products.Remove(p);
    _context.SaveChanges();

    return NoContent();
  }
}

Take some time to look through the code, it should hopefully be quite straight forward to figure out how it works. If you want me to add a working example on GitHub, let me know in the comments.

I you want to test the API during development I recommend a tool like Postman. It is a good tool for sending HTTP requests and checking the responses.