Creating a Blazor WebAssembly Application — Part 2

Henrique Siebert Domareski
8 min readOct 26, 2022

Blazor WebAssembly is a great way to create Single Page Application (SPA) apps using C# language. In this series, I present how to create a Blazor WebAssembly Application from scratch. This is the second article of this series, in which I demonstrate how to implement the Model classes, Interfaces and the Service classes, which are responsible for communicating with the Web API.

The project we are going to use for this demonstration was created during the Part 1 of this series, where I presented an introduction to a Blazor WebAssembly project, and explained how to get started with it. You can read the first article by clicking here.

Blazor WebAssembly Project

Let’s start cleaning the solution that was created, removing what we don’t need for this project. Delete the following files:

Overview of the Back-End Project

Before we dive into the Blazor App, let me give some background information about the project we are going to create in this series. In previous articles, I demonstrated how to create an application using .NET Web API and Angular, and for that, I created the “BookStore” project. So now we are going to create a similar front-end project but with Blazor WebAssembly. And this app will make use of the existent back-end service (Web API).

You can check the code of the back-end project on my GitHub repository by clicking here. And if you want to check the series of articles about this project, check the series “Creating an Application from Scratch using .NET Core and Angular” here on my medium blog. These are the links for the back-end service:

The back-end service contains the following endpoints:

Note: this back-end service was created to be consumed by another SPA project, which was made using Angular, and now we are going to consume the same back-end service but in a Blazor app. This is another benefit of having SPA apps for the front-end solutions, they are totally independent of the technology that is used in the back-end service.

Creating the Model classes

Let’s start creating the model classes that we need for our project, one for Category and one for Book:

If we check the API on Swagger, in the POST method we can see the properties of a Book and a Category. In the image below you can see an example of that:

For Category we only have two properties: Id and a Name:

On line 5 and 6, we added some notations for making the property required, when using it in the UI. With that, when we implement the component, we only need to add a tag for DataAnnotationsValidator, and it will understand that the validation of the field is coming from these notations.

For the Book model, we need the following properties:

The CategoryId (on line 21) is the value we are going to use to save the book’s category, and there is another property named CategoryName on line 23, and this is to be used when we display the category name of a book in the list of books.

IHttpClientFactory

The communication between the SPA and the back-end is done via HTTP requests, and for that we can use the HttpClient or the IHttpClientFactory. For this project we are going to use the IHttpClientFactory (which is the recommendation for most cases). If you want to know the difference between them, you can check an article that I recently wrote about this topic, which can be found on this link.

To use the IHttpClientFactory we need to install the package Microsoft.Extensions.Http in our project. To do that, right-click in your solution > select “Manager NuGet Packages…”:

Then search for the extension Microsoft.Extensions.Http and install it (for this example I’m using the latest current version which is 6.0.10):

Now let’s register the IHttpClientFactory in the Program.cs file. When using IHttpClientFactory, there are many ways to configure it, you can choose between the Named clients, Typed clients, Generated clients, or the Basic usage— if you want to know more about it, and understand when it’s better to use each one, check the documentation about Making HTTP requests using IHttpClientFactory in ASP.NET Core on Microsoft Docs by clicking on this link. For this project, let’s use the default implementation, which can be configured by adding AddHttpClient. In the Program.cs file:

builder.Services.AddHttpClient();

We will need to come back to this same file (Program.cs) to also include the configuration for the Service classes after we create them.

Creating the appsettings.json file

Inside of wwwroot folder, let’s also create an appsettings.json file. To do that, right-click in the folder > Add a new item:

In this file, add the API URL (in this example I’m using localhost):

{
"BookStoreApi": {
"Url": "https://localhost:5001/"
}
}

Creating the Services classes

Now let’s create the services classes, which will be responsible for handling the requests to the back-end service. For that, let’s create a folder for Interfaces and a folder for the Services, and we will later configure the Dependency Injection (DI) for these classes:

Configuring Dependency Injection (DI)

Now we need to configure the DI for the service classes. If you are not familiar with DI or want to know more about DI and Service Lifetimes in .NET, you can check an article I wrote about this topic by clicking here. To configure it for the service classes, add the following configuration in the Program.cs class:

builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<IBookService, BookService>();

In this example, we added the Scoped lifetime, this means that the services are going to be created each time they are requested.

Implementing the Service classes

For both Service classes, we need a method to Add, Read, Update and Delete (CRUD). For demonstration purpose, I’m going to use the BookService as an example, and you can find the complete code in my GitHub by clicking on this link. This is the Interface IBookService:

We can now implement the Service classes for Book and Category. This is the initial of the BookService class, which implements the interface IBookService:

First, we create some private properties, which are going to be used by the methods in this class.

  • On line 3 there is the variable for IConfiguration, which will be used to get the API Url from the appsettings.json file.
  • On line 4 there is the IHttpClientFactory, which will be used to create the HTTP client.
  • On line 5 there is a variable for baseUri, which value comes from the configuration file appsettings.json.
  • On line 7 there is the constructor of the class, which receive the IConfiguration and the IHttpClientFactory via Dependency Injection.
  • On line 10, we are using the _configuration to read the API Url (which is coming from the appsettings.json file), and the value is added to the _baseUri variable.

Now let’s implement in the BookService class the Get methods, one GetAll, which will return a list of all books, and the GetById, which receives the id of a book as a parameter, and returns the book.

  • On line 3, we create an instance of the HttpClient by calling the CreateClient.
  • On line 5, is where the request to the back-end service is being made, and we are using the GetFromJsonAsync passing the type of data that we want to deserialize — which in this case is an IEnumerable<Book>— in an asynchronous operation.
  • On line 7 we return the list of books.
  • The GetById method (line 10) follows the same structure, and there are two differences in this method: first difference, is that this method receives the id of a book as a parameter, and returns a single book instead of a list of books, the second difference is that there is a validation on line 16 (response.IsSuccessStatusCode) to check if the response has a success status code, and in case it has, it will return the book, otherwise, return null. The reason for this check it’s because for the GetById, when there is no book with the searched id, the API returns not found — which means it is not success — , and for the GetAll, in case there are no books, the API returns null.

Next, let’s implement the Add method:

  • On line 1, the Add method receives as a parameter, the book we are going to add.
  • On line 3, we create an instance of the HttpClient by calling the CreateClient.
  • On line 4 serialize the book to a JSON variable.
  • On line 7 we made the Post request to the back-end, with the book to be added.
  • On line 9, we call the response.IsSuccessStatusCode, in order to know if the response of the request on line 7 was successful or not, in case of Successful, it will return true.
  • On line 11 we deserialize the content of the response of the request (the added book), and return it.
  • On line 16 we return null, for the case when the response is not successful.

Next, let’s implement the Update method, which follows a similar structure of the Add method,

  • On line 7 we made a Put request with the updated book.
  • On line 9, in case the response of the request is successful, the method return true, otherwise returns false.

Next, let’s implement the Delete method:

  • On line 5 we make the Delete request informing the id of the book we want to delete.
  • On line 7, in case the response of the request is successful, the method return true, otherwise returns false.

Conclusion

Now we have the Model classes and the Services classes implemented and ready to be used. In the next part, we are going to create the components and pages for Categories and Books.

This is the link for the project in GitHub:

https://github.com/henriquesd/BlazorSPABookStore

If you like this project, I kindly ask you to give a ⭐️ in the repository.

Thanks for reading!

--

--