簡體   English   中英

xamarin 上的 HttpClient PostAsync 什么也不做

[英]HttpClient PostAsync on xamarin does nothing

我有一段代碼

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。

對於所有在同一問題上苦苦掙扎的人 - 這與 SSL(在我的情況下為自簽名證書)有關。 如果您嘗試通過 HTTPS 連接到您的服務器 - 首先嘗試使用純 HTTP,我的應用程序可以正常使用 HTTP,而 HTTPS 掛起。

我也遇到了PostAsync()其他問題,並且在編輯標題和諸如此類的事情方面,它也不像SendAsync()那樣可定制。 我會推薦SendAsync()

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM