I'm creating a custom API client to be used by my web (Blazor WebAssembly Standalone) and mobile (.NET MAUI) apps for connecting to my API. I have two questions below but first, here's an abbreviated version my code:
public class MyApiClient : IMyApiClient
{
public async Task<User> GetUser()
{
// Check for Internet connection
if(!IsConnectedToInternet())
throw new Exception("No Internet connection!");
// Call API to get user info
...
}
public virtual bool IsConnectedToInternet()
{
// Requires platform specific implementation
return false;
}
}
public interface IMyApiClient
{
Task<User> GetUser();
bool IsConnectedToInternet();
}
And in my Blazor app's Program.cs, I inject the HttpClient into MyApiClient this way:
...
builder.services.AddHttpClient<MyApiClient>(client => client.BaseAddress = new Uri("https://www.example.com/api"));
...
My questions are:
- Where do I create the
overridespecific to a web app forIsConnectedToInternet()method? Doing this inProgram.csdoesn't seem right. - I'd like to use the
IMyApiClientinterface inProgram.csinstead of the actualMyApiClientclass. Where do I register theIMyApiClientinterface and its implementation? Do I handle it the way I handle any local services and their interfaces in the Blazor app? For example:builder.services.AddSingleton<IMyApiClient, MyApiClient>();inProgram.cs? If so, is the order important e.g. do I need to inject theHttpClientafter the registration?
HttpClientwill throw an exception, which you can catch by type. rather than justException.HttpClientHandlerchain thatHttpClientuses is an example of the Decorator pattern. You can configure different handlers for each platform to add the access token to the request. That keeps that concern separate from the structure of the request, and applies that consistently across all requests the typed client may need to make.