7

I am used to registering the httpclient in the program.cs of the client project as follows

builder.Services.AddHttpClient("My.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

However this does not work in Blazor .net8. I get errors saying that there is

InvalidOperationException: Cannot provide a value for property 'Http' on type 'My.Client.Pages.RiskReview'. There is no registered service of type 'System.Net.Http.HttpClient'.

What do I need to do to register the httpclient in blazor .net 8?

I am using webassembly rendering

2
  • Can you post the class that is generating the error? The one where the HttpClient is being injected. Commented Nov 29, 2023 at 12:10
  • Did you end up solving the issue? Neither of the provided answers nor [learn.microsoft.com/en-us/aspnet/core/blazor/… page) is working for me. Commented Dec 24, 2023 at 22:48

4 Answers 4

6

My error was a bit different, but installing Microsoft.Extensions.Http NuGet package made .AddHttpClient extension available in the client project.

Sign up to request clarification or add additional context in comments.

Comments

6

I am new to Blazor in general, but I was having the same error in Blazor 8, my setup had two projects, the server and client. the project was setup as webassembly at each component.

program.cs 
// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents();

...

app.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(Client._Imports).Assembly);

What seemed to have been occurring was that the razor component was loading twice, first looks like it was being rendered at the server and the subsequent time at the client.

I was testing the 3 methods to access http, via httpclient, named httpclient and typed httpclient.

My registration was as follows. jsonplaceholder.typicode.com is a public rest api that I used to provide json sample data.

    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https://jsonplaceholder.typicode.com") });

    builder.Services.AddHttpClient("JsonPlaceHolderClient", client =>
    {
        client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
    });

    builder.Services.AddHttpClient<Client.JsonPlaceHolderClient>(client =>
    {
        client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
    });

The razor component had the following

@rendermode InteractiveWebAssembly

If I performed the httpclient registration at the server project, the first time the razor component loaded the httpclient's base address was "https://jsonplaceholder.typicode.com", which tells me it was using the server registration. The subsequent time, the httpclient's base address was null.

If I switched the registration to the client project and commented out the server side project registration, the first razor component load had the base address as null, and the subsequent time it was using the client registration and the base address was correct.

If I changed the razor's component rendermode to

@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))

Then the razor component was loaded once using the registration from the client. This is what I wanted.

This was issue. I wanted the component to execute on the client and didn't think to register the services on the server. The pre-rendering was executing on the server and the http registered services were not found.

HTH.

1 Comment

The only true answer in the web explaining the interactive mode scenarios.
5

This is the way I did it with .NET 8:

builder.Services.AddScoped(http => new HttpClient
{
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
}) ;

2 Comments

builder.HostEnvironment does not exist in Program.cs in .Net 8
Works with .NET 9 as well.
4

You need to add the HttpClient to the service collection to be able to inject it.

/*
 * Configure two named http clients.
 * Named http clients can be accessed by injecting the IHttpClientFactory:
 *
 * [Inject] private IHttpClientFactory ClientFactory { get; set; }
 * var client1 = ClientFactory.CreateClient("My.ServerAPI");
 * var client2 = ClientFactory.CreateClient("ServerAPI.AllowAnonymous");
 */
builder.Services
    .AddHttpClient("My.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services
    .AddHttpClient("ServerAPI.AllowAnonymous", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

/*
 * Add this code to allow My.ServerAPI client to be directly injected
 * as an HttpClient instance:
 *
 * [Inject] private HttpClient Client { get; set; }
 */
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("My.ServerAPI"));

If you only call AddHttpClient then you have to inject the IHttpClientFactory and use var client = ClientFactory.CreateClient("My.ServerAPI"); to get the HttpClient.

3 Comments

Does not work for me.
Thank you for this answer! What's the "My.ServerAPI"
It's a name to identify the specific HttpClient. You can have multiple named clients: .AddHttpClient("Client1", ...), .AddHttpClient("Client2", ...). Check this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.