【问题标题】:HttpClient PostAsync on xamarin does nothingxamarin 上的 HttpClient PostAsync 什么都不做
【发布时间】:2016-05-29 18:43:02
【问题描述】:

我有一段代码

var formContent =
    new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("grant_type", "password"),
        new KeyValuePair<string, string>("username", _userName),
        new KeyValuePair<string, string>("password", _password)
    });

var response = await InternalClient.PostAsync("/Token", formContent).ConfigureAwait(false);

当我在我的桌面应用程序中使用它时,它工作正常,但同样的部分在 Xamarin.Android 上失败了。我可以从模拟器浏览器访问我的网站,所以这不是没有这两者之间的连接的情况。更有趣的部分 - GetAsync 工作得非常好。由于超时,PostAsync 总是失败并出现 TaskCancelledException。所有 PostAsync 调用根本不会访问服务器。
我执行此操作的活动:

var isAuthSuccess = _mainClient.Authenticate();

isAuthSuccess.ContinueWith(task =>
{
    RunOnUiThread(() =>
    {
        if (isAuthSuccess.Result)
        {
            ReleaseEventHandlers();

            var nav = ServiceLocator.Current.GetInstance<INavigationService>();
            nav.NavigateTo("MainChatWindow", _mainClient);
        }

        button.Enabled = true;
    });
});

还有 Authenticate 方法:

public async Task<bool> Authenticate()
{
    var getTokenOperation = new AsyncNetworkOperation<string>(GetTokenOperation);
    var token = await getTokenOperation.Execute().ConfigureAwait(false);

    if (getTokenOperation.IsCriticalFailure)
    {
        SetCriticalFailure(getTokenOperation.FailureReason);
    }

    if (getTokenOperation.IsFailure == false)
    {
        InternalClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
        return true;
    }

    else
    {
        AuthenticationFailEncounteredEvent("Authentication fail encountered: " + getTokenOperation.FailureReason);
        return false;
    }
}

获取令牌操作:

private async Task<string> GetTokenOperation()
{
    var formContent =
            new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("grant_type", "password"),
                new KeyValuePair<string, string>("username", _userName),
                new KeyValuePair<string, string>("password", _password)
            });

    var response = await InternalClient.PostAsync("/Token", formContent).ConfigureAwait(false);
    response.EnsureSuccessStatusCodeVerbose();

    var responseJson = await response.Content.ReadAsStringAsync();

    var jObject = JObject.Parse(responseJson);
    var token = jObject.GetValue("access_token").ToString();

    return token;
}

还有包装器 - AsyncNetworkOperation

public class AsyncNetworkOperation<T>
{
    public bool IsFailure { get; set; }

    public bool IsCriticalFailure { get; set; }

    public string FailureReason { get; set; }

    public bool IsRepeatable { get; set; }

    public int RepeatsCount { get; set; }

    public Func<Task<T>> Method { get; set; }

    public AsyncNetworkOperation(Func<Task<T>> method, int repeatsCount)
    {
        Method = method;
        IsRepeatable = true;
        RepeatsCount = repeatsCount;
    }

    public AsyncNetworkOperation(Func<Task<T>> method)
    {
        Method = method;
    }

    public async Task<T> Execute()
    {
        try
        {
            return await Method().ConfigureAwait(false);
        }

        ...exception handling logics
    }
}

在活动中直接调用 PostAsync 的行为相同 - 等待很长时间,然后由于超时而失败并出现 TaskCancelledException。

【问题讨论】:

  • 1) “失败”到底是什么意思? 2)这种方法的校准堆栈有什么不同吗?
  • 失败是指它抛出异常并且从未真正命中服务器。没有检查调用堆栈差异 - 它只是在我用于桌面和 android 版本的同一个类库中。
  • 添加了更多的源代码,现在图片更准确了
  • @HardLuck InternalClient 是否设置了超时或类似的东西?也许我会尝试删除所有 .ConfigureAwait(false) 代码,看看是否有什么不同。
  • 不,它没有这样的设置,我试过删除 ConfigureAwait,同样的结果。强调两件事:它在 doktop 上运行良好,在 Xamarin 上从活动(而不是从库)调用 PostAsync 也失败了。 GetAsync 无处不在

标签: c# xamarin xamarin.android


【解决方案1】:

对于所有在同一个问题上苦苦挣扎的人 - 这与 SSL(在我的例子中是自签名证书)有关。如果您尝试通过 HTTPS 连接到您的服务器 - 请先尝试使用纯 HTTP,我的应用程序可以正常使用 HTTP,而 HTTPS 挂死。

【讨论】:

  • 很高兴你知道了。为了在服务调用中允许自签名证书,我建议将以下内容添加到您的 MainActivity (或任何地方),这将允许证书(同时注意 DEBUG 语句,因此它不会进入生产环境):#if DEBUG System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslError) =&gt; return true; #endif跨度>
  • 这可能是一个可能的错误,无论我在哪里添加此事件处理程序(库\活动\等),对于不受信任的证书,它总是被忽略。
  • 是的,我在 Android 上遇到了很多自签名证书问题,在 iOS 上更是如此。您可以尝试将自签名证书安装到设备/模拟器中......或者按照您所说的那样停止使用 HTTP,这可能是更容易采取的途径
【解决方案2】:

PostAsync() 也有其他问题,在编辑标题和类似内容方面,它也不像SendAsync() 那样可定制。我会推荐SendAsync()

HttpRequestMessage  request = new HttpRequestMessage(HttpMethod.Post, "/Token") { Content = formContent };
HttpResponseMessage message = await InternalClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);

【讨论】:

  • 不幸的是,SendAsync 与 HttpMethod.Post 的行为相同
  • @HardLuck 那么它一定是其他地方的问题,因为它对我来说很好。也许发布更多代码以查看问题可能是什么。
  • 添加了更多源代码,现在图片更准确
猜你喜欢
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多