As an example the template generated code has
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
and this service is consumed here
@page "/fetchdata"
@inject HttpClient Http
...
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}
Fine, but can I access that service from a plain c# file?
I tried hand typing what the @inject generates but this doesnt seem to work:-
[Inject]
HttpClient Http {get;set;};
EDIT - answer consolidated out of various comments and answers
When a dependency is instantiated by the DI system if its constructor has arguments that are classes or interfaces already registered then
this chain must be initiated by an @inject / [inject]
somewhere on a blazor page.
So to take my example. If I have some code in a class called say, DbIo, that needs the HttpClient. Must do
public class DbIo{
HttpClient _http;
// constructor effectively announcing the dependencies
public DbIo(HttpClient _http){
_http = http;
}
}
add
builder.Services.AddScoped<DbIo>();
to program.cs, and add (this is the not obvious bit)
@inject DbIo DbService
to a blazor page (say App.razor). This forces the instantiation of a DbIo instance and hence the passing of the other services via its constructor.
This is the nature of Dependency Injection. If the root object is provided by the DI Container, then it can resolve all constructor parameters, assuming that they too are registered in the DI Container.
Razor Components/Pages are provided by the Blazor framework and the Blazor framework takes care of resolving the Injected properties (assuming they have been registered in the DI container).
builder.Services.AddScoped(sp =>
new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
... adds HttpClient to the DI Container.
When your FetchData page is provided by the Blazor Framework it will provide services marked with directive @inject. In this case ... HttpClient.
Using a custom service ...
If you want to use a service between your pages and HttpClient so that the page is not working directly with an HttpClient, then you'd need to register that service in the DI Container.
builder.Services.AddScoped<MyCustomService>();
Then, in your razor page, you can inject MyCustomService:
@inject MyCustomService CustomService
Now that MyCustomService is being provided by the DI Container, it can just request the HttpClient in it's Constructor parameters (as the HttpClient is also registered in the DI Container):
public class MyCustomService
{
readonly HttpClient _httpClient;
public MyCustomService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task ApiMethod()
{
await _httpClient.PostAsync( ..... );
}
}