Search code examples
xamarin.formsxamarin.androiddotnet-httpclient

How to set properties in a custom HttpMessageHandler?


I am developing a cross-platform Xamarin Forms app, and I want to be able to use the platform-specific HttpMessageHandler subclasses AndroidClientHandler and NSUrlSessionHandler respectively, when I initialize the HttpClient object.

To accomplish this, I am configuring the Android and iOS app projects to use native HTTP client implementations, and then I use the parameterless constructor to initialize HttpClient:

var client = new HttpClient();

However, I also would like to ensure that AllowAutoRedirect and UseCookies of the message handler are set to false. There is no Handler property in the HttpClient class. How can I ensure that these handler properties are correctly set in the implicitly initialized handler objects?

Since this is cross-platform code, I would like to avoid as much as possible to resort to using the HttpClient(HttpMessageHandler) constructor and explicitly pass in platform-specific handler instances. If at all possible, I would like to be able to pre-configure the properties of the handlers that are initialized in the parameterless constructor.

EDIT

From API documentation, it is easy to get the impression that the platform-specific handler implementations will be applied if you pass a HttpClientHandler object to the HttpClient constructor:

var handler = new HttpClientHandler
{
  AllowAutoRedirect = false,
  UseCookies = false
};
var client = new HttpClient(handler);

Unfortunately, the above does not work in practice. With this approach, a HttpClientHandler object will be instantiated, regardless of whether HttpClient implementation has been set to native in the project settings.

In theory, one alternative would be if there was any way to obtain an instance of the handler that is initialized in the parameterless constructor, modify it and pass the modified instance into the HttpMessageHandler argument constructor, something like this:

var handler = GetHandlerInstanceAppliedInParameterlessHttpClientConstructor();
handler.AllowAutoRedirect = false;
handler.UseCookies = false;
var client = new HttpClient(handler);

However, I am not aware of any method returning such a handler instance.

I should also point out that my main concern right now is Android, so an answer that applies primarily to Android might be enough.


Solution

  • You don't need to expose the native handlers and implement it for both platforms. HttpClient accepts an overload with a handler, like you stated. However, that handler is a .NET Standard handler. So, if you initialise the handler in the shared project, or inherit from it in the native ones, they are the same type of class.

    In your shared project, you can simply initialise the client like this:

    var handler = new HttpClientHandler
    {
        AllowAutoRedirect = false,
        UseCookies = false
    };
    var client = new HttpClient(handler);
    

    However, this way you will override the "native" handler and will use HttpClientHandler instead.

    Additional remarks, based on comments and edited question:

    To answer your question - no, there isn'y any built-in way to get the AndroidClientHandler in the shared code. You'll have to expose it yourself. You can also write your own native handlers and expose them through a DependencyService and then invoke the ctor with them. The latter I have done in the past and it worked with no issues.