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

Posted

技术标签:

【中文标题】Xamarin - 在 .Net 标准库中使用 httpClient【英文标题】:Xamarin - Using httpClient in .Net Standard Library 【发布时间】:2018-07-05 14:13:29 【问题描述】:

我创建了 Xamarin 项目,并向其中添加了几个 .Net 标准类库(每一层一个:数据访问、服务层等)。然后,在 ServiceLayer 项目中,我实现了从我的 Web API(外部 ASP Net Core 项目)获取数据的方法。当涉及到 httpClient.GetAsync() 时,android 应用程序崩溃。更重要的是,当我剪切这段代码并将其粘贴到默认的 xamarin .Net 标准库中时,一切正常。有任何想法吗?

代码在这里:

HttpClient httpClient = new HttpClient();
var responseMessage = await httpClient.GetStringAsync(uri);

更新:

在视图模型中:

constructor(IServiceLayerService service)
        _ServiceLayerService = service;
        GetTestCommand = new DelegateCommand(async () => await GetTests());
             

        public async Task GetTests()
        
            TestObservableCollection = new ObservableCollection<List<Test>>(await _ServiceLayerService.GetTestModels());
        

更新 2: 我已经按照第一个答案中介绍的方式更改了我的异步方法调用。现在,当我尝试执行代码时,应用程序也崩溃了,但我收到了错误消息:

07-05 14:39:04.518 F/        (25383): /Users/builder/jenkins/workspace/xamarin-android-d15-7/xamarin-android/external/mono/mono/mini/debugger-agent.c:4897: Could not execute the method because the containing type is not fully instantiated. assembly:<unknown assembly> type:<unknown type> member:(null) signature:<none>
07-05 14:39:04.518 F/libc    (25383): Fatal signal 6 (SIGABRT), code -6 in tid 25383 (com.companyname), pid 25383 (com.companyname)

也许我在Unity依赖注入方面做错了,所以这里是在App.xaml.cs中注册服务层类

 protected override void RegisterTypes(IContainerRegistry containerRegistry)
        
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<TestsListPage, TestsListViewModel>();
            containerRegistry.Register<IServiceLayerService, ServiceLayerService>();

【问题讨论】:

当代码崩溃时如何以及在哪里被调用?您是否在拨打.Result.Wait() 之类的阻塞电话? 我将 ServiceLayer 项目中的类注入 ViewModel,然后在命令中执行它。 显示。很可能您的命令中有一个异步 void 不允许您捕获异常。 我已经用代码更新了问题 是的 GetTestCommand = new DelegateCommand(async () =&gt; await GetTests()); 创建一个异步 void。创建一个事件处理程序并在命令中引发它。 【参考方案1】:

问题在于异步命令委托

GetTestCommand = new DelegateCommand(async () => await GetTests());

命令委托导致async void,它不允许捕获异常,因为它们被认为是触发和遗忘方法

参考Async/Await - Best Practices in Asynchronous Programming

创建一个事件和处理程序来管理异步调用

private event EventHandler gettingTests = delegate  ;
private async void OnGettingTests(object sender, EventArgs args) 
    try 
        await GetTests();
     catch (Exception ex) 
        //...handle exception
    

请注意,事件处理程序是允许async void的规则的一个例外情况@

在构造函数中订阅事件并在命令委托中引发事件

constructor (IServiceLayerService service) 
    _ServiceLayerService = service;
    this.gettingTests += OnGettingTests;
    GetTestCommand = new DelegateCommand(() => gettingTests(this, EventArgs.Empty));
 

所以现在当命令被调用时,它将引发事件并且异步处理程序可以正确地进行异步调用。

【讨论】:

我已经按照您介绍的方式更改了我的方法调用,但应用程序仍然崩溃。我放置了断点,并注意到在 GetStringAsync 调用后应用程序在 ServiceLayer 项目中崩溃。不幸无一例外。输出的最后一条消息是:xamarin-android/external/mono/mono/mini/debugger-agent.c:4897: Could not execute the method because the containing type is not fully instantiated. assembly:&lt;unknown assembly&gt; type:&lt;unknown type&gt; member:(null) signature:&lt;none&gt; (25383): Fatal signal 6 (SIGABRT), code -6 in tid 25383 (name), pid 25383 (name) @Movart 但现在您可以捕获异常以查看原因并排除故障。使用 async void 委托,您无法做到这一点。 是的,我明白了,谢谢。现在我看到了这些消息,我正在尝试修复它们。我想,我在 Unity 依赖注入方面做错了,但我不知道是什么

以上是关于Xamarin - 在 .Net 标准库中使用 httpClient的主要内容,如果未能解决你的问题,请参考以下文章

使用 .Net 标准库中的 UWP 方法

.net 标准库中的 HttpContext

从 .net 标准库中读取 appsettings.json

从 .net 核心控制台应用程序引用 .net 标准 2.0 库中的 dll 时出错

在 .NET 6.0 类库中使用 Prism.DryIoc 时“目标平台必须设置为 Windows”

使用 Xamarin 在可移植类库中保护 WCF 绑定