0

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:

  1. Where do I create the override specific to a web app for IsConnectedToInternet() method? Doing this in Program.cs doesn't seem right.
  2. I'd like to use the IMyApiClient interface in Program.cs instead of the actual MyApiClient class. Where do I register the IMyApiClient interface 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>(); in Program.cs? If so, is the order important e.g. do I need to inject the HttpClient after the registration?
11
  • 1
    You need to learn .NET and OOP basics first. There is no a predefined procedure of interface registration, it is not needed. Now, the place where you override methods or implement interface methods is not related to C# files. You have the freedom to make decisions on class design and code location totally independently. Commented 2 days ago
  • 1
    I don't think the typed client is a proper place to do that check. That's more of a UI concern, where you present an indication to the user that the device is offline. A typed client should have absolutely zero knowledge about the UI. If the device is offline, HttpClient will throw an exception, which you can catch by type. rather than just Exception. Commented 2 days ago
  • 1
    You should use composition to separate this concern from the core concerns of a typed client. Create a service that consumes the typed client and does the connection check before using it. It should also consume a platform-specific service that knows how to do the connection check for that platform, and another that knows how to manipulate the UI to inform the user. Commented 2 days ago
  • 2
    Definitely not cleaner because concerns are co-mingled. Commented 2 days ago
  • 1
    The HttpClientHandler chain that HttpClient uses 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. Commented 2 days ago

1 Answer 1

0

As already mentioned, it's totally up to you how you implement it.

But I wanted to point out one thing that is crucial to this consideration - MAUI already includes solutions to "platform specific implementations", which makes use of preprocessor directives. See Target multiple platforms from .NET MAUI single project | Platform-specific code:

#if ANDROID
                  handler.PlatformView.SetBackgroundColor(Colors.Red.ToPlatform());
#elif IOS
                  handler.PlatformView.BackgroundColor = Colors.Red.ToPlatform();
                  handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.Line;
#elif WINDOWS
                  handler.PlatformView.Background = Colors.Red.ToPlatform();
#endif

You could borrow that idea into your codebase.

Having said that, it's really up to you what kind of code (implementation, registering different types of implementation for the interface) you will wrap under such directives.

To give you example, you could keep your current setup in tact and just use directives inside IsConnectedToInternet method (in fact, you don't need virtual anymore)

public bool IsConnectedToInternet()
{
#if ANDROID
    // check internet on android device
#elif IOS
    // check internet on IOS device
#elif WINDOWS
    // check internet on WINDOWS device
#else
    // check web api internet connection
#endif
}
Sign up to request clarification or add additional context in comments.

Comments

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.