(5/30) Learning Blazor Together: Dependency Injection

(5/30) Learning Blazor Together: Dependency Injection

The question is, how does Blazor know that WeatherForecastService can be invoked here?

Last updated 12/11/2021 1:27 PM
StrayaWorker
3 min read
Category
Blazor
Topic
Learning Blazor Series
Tags
.NET C# ASP.NET Core Blazor

So why does Blazor know that WeatherForecastService can be called here?

Open Program.cs and you’ll find the following line:

builder.Services.AddSingleton<WeatherForecastService>();

If you comment out this line, reload the page, and click the Fetch data menu, you’ll see an exception warning in the page (only a warning block appears in the footer). For detailed warnings, check the terminal output — because we’re trying to call WeatherForecastService in FetchData.razor, but we haven’t told Blazor to register this service.

Page exception warning

Terminal exception output

Let’s copy that warning for clarity:

Cannot provide a value for property 'ForecastService' on type 'BlazorServer.Pages.FetchData'. There is no registered service of type 'BlazorServer.Data.WeatherForecastService'.

But this isn’t about dependency injection as discussed in day03. The purpose of dependency injection is to free high-level programs from depending on low-level programs, reducing coupling. For example, if FetchData.razor needs to call another service, like NewWeatherForecastService with the same method name GetForecastAsync, and retrieve 10 records, then everywhere that uses WeatherForecastService must be updated. In this small demo it might not feel like a big deal, but what if there are 10 or 20 places to change?

That’s where dependency injection shines. First, define an interface: IWeatherForecastService

namespace BlazorServer.Data;

public interface IWeatherForecastService
{
	Task<WeatherForecast[]> GetForecastAsync(DateTime startDate);
}

Inside, we write the method we need: Task<WeatherForecast[]> GetForecastAsync(DateTime startDate);

There’s no implementation yet (though interfaces can have default implementations — Editor’s note: C# 8.0 introduces default implementations for interfaces, making it easier to extend existing implementations and enabling interop with Android and Swift APIs.). Then we make WeatherForecastService and NewWeatherForecastService implement IWeatherForecastService.

Service implements interface

In Program.cs, we register IWeatherForecastService with NewWeatherForecastService.

Interface injection service

As shown in the screenshot above, in FetchData.razor, we also change the injection to IWeatherForecastService.

After refreshing the page, you’ll see the data count becomes 10 records.

10 records display

The core of dependency injection is that “dependence on a certain functionality is injected.” Instead of directly calling the low-level program, we call its interface. Even if the low-level program changes, all callers that rely on it don’t have to be modified.

Note: The author intended to explain the lifecycle after writing this article and originally planned to use git rebase to go back to this commit and add a demo, but that could lead to a detached HEAD issue. Therefore, the lifecycle will be explained on day 07. Apologies for any inconvenience.

Note: The code in this article has been refactored using .NET 6 and Visual Studio 2022. You can click the original link to compare the refactored code with the original. Thank you for reading, and please support the original author.

Keep Exploring

Related Reading

More Articles
Same category / Same tag 12/25/2021

(29/30)Learn Blazor Together: Blazor Unit Testing

The most boring part of developing a system is probably fixing bugs, especially errors like trying to access a null object (`Object reference not set to an instance of an object.`), which is the most common problem most people encounter when they first step into programming. To break free from the tedious bug-fixing process, this article introduces `unit testing`.

Continue Reading
Same category / Same tag 12/25/2021

(28/30) Learning Blazor Together: Policy-based Authorization

It was mentioned earlier that `ASP.NET Core Identity` uses `Claim`-based authentication. In fact, `ASP.NET Core Identity` has different types of authorization methods, the simplest being `Login Authorization`, `Role Authorization`, and `Claim Authorization`. However, all of the above are implemented in one way: Policy-based Authorization.

Continue Reading