tpe_001
tpe_001

Reputation: 13

Blazor Hybrid .NET MAUI using HttpClient

I'm using Blazor Hybrid with .NET MAUI in combination with a REST Web API to fetch data.

To get my data from the API, I use a service (e.g. UserService) and the service needs an httpClient. The service uses a base class ServiceBase to do the actual work

Currently I use the new() keyword to instantiate the httpClient in a private read-only property in the ServiceBase class:

public class UserService : ServiceBase, IUserService
{
    public UserService(ILogger<UserService> l, HttpClient c)
        : base(l, c)
    { }

    protected readonly HttpClient _httpClient = new();
    protected readonly ILogger _logger;

    public ServiceBase(ILogger logger, HttpClient client)
    {
        _httpClient = client;
        _logger = logger;
    }

    protected async Task<Result<T>> GetFromJson<T>(string url)
    {
        try
        {
            var result = await _httpClient.GetFromJsonAsync<T>(url);
            return result;
        }
        catch (Exception e)
        {
            _logger.LogError(e, e.GetResultMessageFromError());
            return Result.Error(e.GetResultMessageFromError());
        }
    }
}

The service is registered as a scoped-service in DI container

builder.Services.AddScoped<IUserService, UserService>();

Normally, when working with the httpClient, I use the typed clients configuration to ensure that the resources are released correctly at the end. But in a course about Blazor Hybrid, it was said that the suggested way is to use the new() keyword (I don't know why).

To be clear, this currently works without any problems.

My question: what is the best way to use the HttpClient and not get the usual problems if you use the HttpClient incorrectly, and why does the use of new() in this context not lead to these issues?

By the way, I tried to use the typed client way but the httpClient is never instantiated correctly, may someone can figure out the problem here.

Typed client configuration in MAUIProgram.cs:

builder.Services.AddHttpClient<UserServiceHttpTestTyped>((serviceProvider, client) =>
  {
      client.DefaultRequestHeaders.Add("Accept", "application/json");
      client.DefaultRequestHeaders.Add("x-test-header", "user Service factory");
      client.BaseAddress = new Uri("https://localhost:7263/");
  });

This time I use the .AddTransient() to register the service (to have the same lifetime as the httpClient):

  builder.Services.AddTransient<IUserService, UserServiceHttpTestTyped>();
public class UserServiceHttpTestTyped : IUserService
{
     private readonly ILogger _logger;
     private readonly HttpClient _client;

     public UserServiceHttpTestTyped(ILogger<UserService> l, HttpClient c)
     { 
         _logger = l;
         _client = c ?? throw new ArgumentNullException(nameof(UserServiceHttpTestTyped));
     }

     [Authorize(Policy = CustomPolicy.CanRead_Users)]
     public async Task<Result<User>> GetUser(Guid id)
     {
         _logger.LogDebug("Get the user with if '{id}'", id);

         var u = Api.Url(Api.GetUserById, id.ToString());

         return await _client.GetFromJsonAsync<User>(u);
     }
}

And the client in the moment of use:

Using the httpClient in a service to fetch data

Upvotes: 0

Views: 98

Answers (0)

Related Questions