如何在自定义 HttpMessageHandler 中设置属性?

Posted

技术标签:

【中文标题】如何在自定义 HttpMessageHandler 中设置属性?【英文标题】:How to set properties in a custom HttpMessageHandler? 【发布时间】:2020-06-02 08:04:50 【问题描述】:

我正在开发一个跨平台的 Xamarin Forms 应用程序,我希望能够在初始化 HttpClient 对象时分别使用平台特定的 HttpMessageHandler 子类 androidClientHandlerNSUrlSessionHandler

为此,我将 Android 和 ios 应用程序项目配置为使用本机 HTTP 客户端实现,然后使用无参数构造函数初始化 HttpClient

var client = new HttpClient();

但是,我还想确保消息处理程序的AllowAutoRedirectUseCookies 设置为falseHttpClient 类中没有 Handler 属性。如何确保在隐式初始化的处理程序对象中正确设置这些处理程序属性?

由于这是跨平台代码,我想尽可能避免使用HttpClient(HttpMessageHandler) 构造函数并显式传递特定于平台的处理程序实例。如果可能的话,我希望能够预先配置在无参数构造函数中初始化的处理程序的属性。

编辑

从 API 文档中,很容易得到这样的印象,即如果您将 HttpClientHandler 对象传递给 HttpClient 构造函数,将应用特定于平台的处理程序实现:

var handler = new HttpClientHandler

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

很遗憾,上述方法在实践中不起作用。 使用这种方法,HttpClientHandler 对象将被实例化,无论 HttpClient 实现是否已在项目设置中设置为原生。

理论上,如果有任何方法可以获取在无参数构造函数中初始化的处理程序的实例,修改它并将修改后的实例传递给HttpMessageHandler 参数构造函数,那么另一种选择是:

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

但是,我不知道有任何方法返回这样的处理程序实例。

我还应该指出,我现在主要关心的是 Android,所以一个主要适用于 Android 的答案可能就足够了。

【问题讨论】:

【参考方案1】:

您无需公开本机处理程序并为两个平台实现它。 HttpClient 接受处理程序的重载,如您所说。但是,该处理程序是 .NET Standard 处理程序。因此,如果您在共享项目中初始化处理程序,或者在本机项目中从它继承,它们是相同类型的类。

在您的共享项目中,您可以像这样简单地初始化客户端:

var handler = new HttpClientHandler

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

但是,这样您将覆盖“本机”处理程序并改用 HttpClientHandler。

补充说明,基于 cmets 和已编辑的问题:

要回答您的问题 - 不,没有任何内置方法可以在共享代码中获取 AndroidClientHandler。你必须自己暴露它。您还可以编写自己的本机处理程序并通过 DependencyService 公开它们,然后使用它们调用 ctor。后者我过去做过,它没有任何问题。

【讨论】:

嗯,我的经验是,这不是使用HttpMessageHandler 参数构造函数会发生什么。在调试Android应用程序时,我看到当我使用您的方法时,_handler 实例的类型为HttpClientHandler,而如果我使用无参数构造函数,_handler 实例的类型为AndroidCleintHandler 是的,但是AndroidClientHandler 继承自System.Net.Http.HttpClientHandler docs.microsoft.com/en-us/dotnet/api/… 而且行为也不同。使用无参数构造函数时,我不会崩溃,而在使用 HttpClient(handler) 时,我 do 会崩溃(鉴于我当前正在调试的特定场景)。所以不,使用您建议的方法似乎不是前进的方向。 是的,AndroidClientHandler 继承自 HttpClientHandler,但调试模式下的实例仍应显示为 AndroidClientHandler,如果这是实际实例化的。 对。我最近尝试了您建议的所有方法。我本来希望有一些捷径,因为现在需要处理的方式似乎还没有经过充分考虑。我在 Xamarin Android 中的自定义 HTTP 客户端处理程序的文档页面上提出了类似的问题,希望至少有人认识到这些缺点。

以上是关于如何在自定义 HttpMessageHandler 中设置属性?的主要内容,如果未能解决你的问题,请参考以下文章

从配置文件配置 HttpClient/HttpMessageHandler

初始化后将 HttpMessageHandler 设置为 HttpClient 的实例

干货.NET WebApi HttpMessageHandler管道

是单例 HttpClient X 分钟后接收新的 HttpMessageHandler

使用特定的 HttpMessageHandler 注入单实例 HttpClient

如何在自定义对话框上显示进度对话框?