使用 Xamarin 表单的 HttpClient

Posted

技术标签:

【中文标题】使用 Xamarin 表单的 HttpClient【英文标题】:HttpClient using Xamarin Forms 【发布时间】:2018-05-14 10:07:41 【问题描述】:

我正在开发一个 Xamarin 表单应用程序,但不确定这是由 C#/HttpClient 还是由 Xamarin Forms 触发的错误。

在我的 Xamarin Forms 应用程序中,我有一个包含以下代码的 RequestService 类:

public class RequestService : IRequestService

    private static HttpClient instance;
    private static HttpClient HttpClientInstance => instance ?? (instance = new HttpClient(new NativeMessageHandler()  EnableUntrustedCertificates = true, DisableCaching = true ));
    public async Task<TResult> GetAsync<TResult>(string uri, string token = "")
    
        setupHttpClient(token);
        HttpResponseMessage response = await HttpClientInstance.GetAsync(uri).ConfigureAwait(false);
        await HandleResponse(response);
        string responseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        return await Task.Run(() => JsonConvert.DeserializeObject<TResult>(responseData));
    

    private void setupHttpClient(string token = "")
    
        HttpClientInstance.DefaultRequestHeaders.Accept.Clear();
        HttpClientInstance.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        if (!string.IsNullOrWhiteSpace(token))
        
            HttpClientInstance.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token);
        
    

    private async Task HandleResponse(HttpResponseMessage response)
    
        if (!response.IsSuccessStatusCode)
        
            var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            if (response.StatusCode == HttpStatusCode.Forbidden || response.StatusCode == HttpStatusCode.Unauthorized)
            
                throw new Exception(content);
            
            throw new HttpRequestException(content);
        
    

过去 5 到 7 天它一直运行良好,但今天它开始崩溃而没有任何错误。任何请求都会退出应用程序。

我设法调试并跟踪成功执行,直到该行:

    HttpResponseMessage response = await HttpClientInstance.GetAsync(uri).ConfigureAwait(false);

它在这条线上尝试做某事,然后退出应用程序。该行的调试控制台显示以下内容:

Thread started:  #3
05-14 10:20:51.974 D/Mono    (20217): Assembly Ref addref ModernHttpClient[0x7028fef180] -> System[0x701365c000]: 15
05-14 10:20:51.986 D/Mono    (20217): Assembly Ref addref ModernHttpClient[0x7028fef180] -> System.Core[0x701439c500]: 10
05-14 10:20:52.098 D/Mono    (20217): DllImport searching in: '__Internal' ('(null)').
05-14 10:20:52.098 D/Mono    (20217): Searching for 'java_interop_jnienv_new_object_array'.
05-14 10:20:52.098 D/Mono    (20217): Probing 'java_interop_jnienv_new_object_array'.
05-14 10:20:52.098 D/Mono    (20217): Found as 'java_interop_jnienv_new_object_array'.
05-14 10:20:52.101 D/Mono    (20217): DllImport searching in: '__Internal' ('(null)').
05-14 10:20:52.101 D/Mono    (20217): Searching for 'java_interop_jnienv_set_object_array_element'.
05-14 10:20:52.101 D/Mono    (20217): Probing 'java_interop_jnienv_set_object_array_element'.
05-14 10:20:52.101 D/Mono    (20217): Found as 'java_interop_jnienv_set_object_array_element'.
05-14 10:20:52.107 D/Mono    (20217): DllImport searching in: '__Internal' ('(null)').
05-14 10:20:52.107 D/Mono    (20217): Searching for 'java_interop_jnienv_get_object_array_element'.
05-14 10:20:52.107 D/Mono    (20217): Probing 'java_interop_jnienv_get_object_array_element'.
05-14 10:20:52.107 D/Mono    (20217): Found as 'java_interop_jnienv_get_object_array_element'.
05-14 10:20:52.213 D/Mono    (20217): DllImport searching in: '__Internal' ('(null)').
05-14 10:20:52.214 D/Mono    (20217): Searching for 'java_interop_jnienv_call_boolean_method'.
05-14 10:20:52.214 D/Mono    (20217): Probing 'java_interop_jnienv_call_boolean_method'.
05-14 10:20:52.214 D/Mono    (20217): Found as 'java_interop_jnienv_call_boolean_method'.
05-14 10:20:52.348 F/        (20217): /Users/builder/jenkins/workspace/xamarin-android-d15-6/xamarin-android/external/mono/mono/mini/debugger-agent.c:4846: (null) assembly:mscorlib.dll type:BadImageFormatException member:<none>
05-14 10:20:52.354 F/libc    (20217): Fatal signal 6 (SIGABRT), code -6 in tid 20217 (com.companyname.appname), pid 20217 (com.companyname.appname)

这里有几点需要注意:

    我正在使用 ModernHttpClient Android Project -> Properties -> Android Options -> 下的设置为: HttpClient 实现 = Android SSL/TLD 实施 = 原生 TFS 1.2+

有人遇到过这个问题吗?任何帮助将不胜感激。

谢谢

【问题讨论】:

我将从请求中删除 ConfigureAwait 开始。等待同步任务没有意义。然后我发现最好的方法是在你的方法周围加上一个 try catch 并从那里调试异常。至少它会帮助你更好地理解问题。 BadImageFormatException 当动态链接库(DLL)或可执行程序的文件映像无效时抛出的异常。你更新了什么吗? @whiskeycoder 是如何同步的?您只能等待异步任务,并且只能配置等待等待的任务。删除它将导致继续在捕获的上下文中恢复,但不会导致可观察到的差异。 感谢您的意见。我已经删除了 ConfigureAwait 并尝试在该行周围包装一个 try...catch。调试器到达该行,然后退出调试。它没有进入异常部分。我在另一个简单的解决方案here 中重现了错误。 @TheGeneral:我花了一些时间才发现,但是是的,将 XF 更新到了最新的稳定版本,并且 Modernhttpclient-updated 到了与 XF v3+ 大约同时发布的 v2.7.0。顺便提一句!! BadImageException 行翻译成什么? 【参考方案1】:

好的!因此,通过执行以下操作解决了这个问题:

    升级到最新版本的 Xamarin 表单。 摆脱 ModernHttpClient,因为第 3 点不再需要它。 ModernHttpClient 的功能(即本机 SSL/Tls)现已内置到 Xamarin 中,现在可以按照以下链接在平台级别进行配置:

ios - https://docs.microsoft.com/en-us/xamarin/cross-platform/macios/http-stack

Android - https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=windows

【讨论】:

以上是关于使用 Xamarin 表单的 HttpClient的主要内容,如果未能解决你的问题,请参考以下文章

当 API 关闭时,Xamarin 表单依赖注入 HttpClient 超时不起作用

Xamarin 表单 HttpClient GetAsync

Xamarin.Forms 使用HttpClient上传文件

Xamarin - 在 .Net 标准库中使用 httpClient

Xamarin 中的 WebException,使用 HttpClient

HttpClient 不可用共享库项目 Xamarin