xamarin - 在 Xamarin Forms 中挂起的 PostAsync 在模拟器上工作,但在实际手机上挂起
问题描述
我有 Xamarin Forms 项目,我正在尝试向/从 Web API 发布和获取数据,但是当我进行异步/等待调用时,它可以在模拟器上运行(并非没有原始问题!)但是当我尝试它在我的实际手机(三星 S8+)上,它只是无限期挂起。
请注意,我现在只专注于 Android 部分,而不是 iOS,并不是说问题应该对两者都有任何影响。
这是我正在使用的代码:
IDataService.cs
Task<TResponse> PostDataAsync<TRequest, TResponse>(string uri, TRequest data)
where TRequest : class
where TResponse : class;
数据服务.cs:
public async Task<TResponse> PostDataAsync<TRequest, TResponse>(string
additionalUri, TRequest data)
where TRequest : class
where TResponse : class
{
return await WebClient
.PostData<TRequest, TResponse>
(string.Concat(this.Uri, additionalUri), data);
}
Web客户端.cs
using (var client = new HttpClient())
{
var jsonData = JsonConvert.SerializeObject(data);
using (var response = await client.PostAsync(
uri,
new StringContent(jsonData,
Encoding.UTF8,
"application/json" )))
{
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResponse>(content);
}
}
}
方法一:
LoginPageViewModel.cs
public DelegateCommand SignInCommand => _signInCommand ??
(this._signInCommand = new DelegateCommand(SignInCommandAction));
private async void SignInCommandAction()
{
try
{
....
var user = await this._dataService
.PostDataAsync<LoginRequestDto,
LoginResponseDto>(@"Accounts/Login", loginRequestDto);
....
}
...
}
方法2:
LoginPageViewModel.cs
public DelegateCommand SignInCommand => _signInCommand ??
(this._signInCommand =
new DelegateCommand(async () => await SignInCommandAction()));
private async Task SignInCommandAction()
{
try
{
....
var user = await this._dataService
.PostDataAsync<LoginRequestDto,
LoginResponseDto>(@"Accounts/Login", loginRequestDto);
....
}
...
}
当我调用本地 Web API 即http://10.0.2.2/MyApp/api/时,PostDataAsync 可以使用这两种方法,但是当从 Web 提供程序(即http://myapp-123-site)调用外部我的 Web 服务时,这两种方法仍然挂起.atempurl.com/api/这是一个用于测试目的的临时 url。
这同样适用于我的 GetDataAsync,它没有被证明,但我只是想我会提到它。
基于上述,您会认为我的 async/await 代码是正确的,因为它在调用本地 web api 时有效,但是在调用远程 web api 时导致它挂起。
如前所述,我确实在清单中启用了我的 INTERNET 权限。
欢迎提出任何建议?
谢谢。
更新-1:
请注意,我刚刚尝试在同一函数中调用 GET 操作,这在模拟器中工作,但与实际的手机挂起。
using (var client = new HttpClient())
{
using (var response = await client.GetAsync(uri))
{
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return Newtonsoft.Json.JsonConvert
.DeserializeObject<TResponse>(content);
}
}
}
更新2:
这在某种程度上有效,我不知道为什么!唯一想到的是我升级了我的库。这包括棱镜,它可能是问题的根源,但我不知道。
抱歉,我无法提供更多细节。我可以恢复我的代码并尝试查看它是否再次挂起,但考虑到我已经花在这方面的时间,我只是没有时间去尝试更多。对不起。
解决方案
请求的 url 是IP或域名。
- 如果是ip,则多个网段的设备只能访问公网的IP。
- 如果是域名,需要支持域名解析服务。
如果暂时没有这些环境,需要设备IP和服务器IP在同一网段。
当我调用本地 Web API 即http://10.0.2.2/MyApp/api/时,PostDataAsync 可以使用这两种方法,但是当从 Web 提供程序(即http://myapp-123-site)调用外部我的 Web 服务时,这两种方法仍然挂起.atempurl.com/api/这是一个用于测试目的的临时 url。
从这个现象来看,应该是临时url的原因。从 这个 域名 ( myapp-123-site.atempurl.com
) 中 找不到 正确 的 本地 IP ( 10.0.2.2
) . 当 你 在 本地 网络 测试 时 , 我 猜 这 会 工作 . 但是 实际 手机 的 网络 可能 和 本地 网络 不 一样 , 比如 使用 3G / 4G网络,那就不行了。
推荐阅读
- perl - directory/.pm 曾经是一个约定吗?它为什么存在?
- elasticsearch - 带有 elasticsearch-rest-high-level-client 的 ElasticSearch 代码未部署在嵌入式 Jetty 8 中
- salesforce - 如何将 soql 计数的聚合结果存储在列表中
- php - 从 Laravel 隐藏填充模型
- r - 当我有不规则的时间序列数据时,如何使用 1 小时滚动窗口计算 sd(x)?
- asp.net-core - 本地化默认数据注释
- python - 如何将名称与 Python txt 文件中的密码相关联?
- image-processing - 我可以使用 Python 和 Pillow 使用自定义权重而不是内置的亮度变换权重将彩色图像转换为灰度吗?
- typescript - 带有静态函数的 Typescript 类,实现了带有字符串索引的接口
- vuejs2 - 组件已安装但模板标签未在生产环境中呈现(但在开发中呈现): Nuxtjs Vuejs Vuetifyjs Rollupjs