C# xamarin上的HttpClient PostAsync不执行任何操作

C# xamarin上的HttpClient PostAsync不执行任何操作,c#,xamarin,xamarin.android,C#,Xamarin,Xamarin.android,我有一段代码 var formContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "password"), new KeyValuePair<string, string>("username", _userName), new KeyValuePair<string, st

我有一段代码

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);
var formContent=
新FormUrlEncodedContent(新[]
{
新的KeyValuePair(“授权类型”、“密码”),
新的KeyValuePair(“用户名”、_用户名),
新的KeyValuePair(“密码”、\u密码)
});
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;
    });
});
var isAuthSuccess=\u mainClient.Authenticate();
isAuthSuccess.ContinueWith(任务=>
{
RunOnUiThread(()=>
{
if(isAuthSuccess.Result)
{
ReleaseEventHandlers();
var nav=ServiceLocator.Current.GetInstance();
导航到(MainChatWindow,_mainClient);
}
button.Enabled=true;
});
});
以及验证方法:

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;
    }
}
公共异步任务身份验证()
{
var getTokenOperation=新的异步网络操作(getTokenOperation);
var token=await getTokenOperation.Execute().ConfigureAwait(false);
if(getTokenOperation.IsCriticalFailure)
{
SetCriticalFailure(getTokenOperation.FailureReason);
}
if(getTokenOperation.IsFailure==false)
{
InternalClient.DefaultRequestHeaders.Add(“授权”、“承载人”+令牌);
返回true;
}
其他的
{
AuthenticationFailEncomedEvent(“身份验证失败:+getTokenOperation.FailureReason”);
返回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;
}
private异步任务GetTokenOperation()
{
var formContent=
新FormUrlEncodedContent(新[]
{
新的KeyValuePair(“授权类型”、“密码”),
新的KeyValuePair(“用户名”、_用户名),
新的KeyValuePair(“密码”、\u密码)
});
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(“访问令牌”).ToString();
返回令牌;
}
以及包装器异步网络操作

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
    }
}
公共类异步网络操作
{
公共bool IsFailure{get;set;}
public bool IsCriticalFailure{get;set;}
公共字符串失败原因{get;set;}
公共bool是可复制的{get;set;}
公共int repeatsunt{get;set;}
公共Func方法{get;set;}
公共异步网络操作(Func方法,int repeatsunt)
{
方法=方法;
IsRepeatable=true;
repeatsunt=repeatsunt;
}
公共异步网络操作(Func方法)
{
方法=方法;
}
公共异步任务执行()
{
尝试
{
return await Method().ConfigureAwait(false);
}
…异常处理逻辑
}
}

在活动中正确调用PostAsync的行为与此相同-等待相当长的时间,然后由于超时而导致TaskCancelledException失败。

我在
PostAsync()
方面也遇到了其他问题,而且在编辑头等方面,它也不像
SendAsync()
那样可自定义。我建议
SendAsync()


对于所有与同一问题斗争的人来说,这与SSL(在我的例子中是自签名证书)有关。如果您试图通过HTTPS连接到您的服务器-请先尝试使用普通HTTP,我的应用程序可以在HTTPS挂起时正常使用HTTP

不幸的是,SendAsync与
HttpMethod.Post一起执行same@HardLuck那么这肯定是其他地方的问题,因为它对我来说很好。可能会发布更多的代码以了解问题所在。添加更多的源代码以使图片现在更准确1)你所说的“失败”到底是什么意思?2) 这个方法的cal堆栈有什么不同吗?所谓失败,我的意思是它抛出一个异常,并且从未真正命中服务器。没有检查调用堆栈差异-它只是在我用于桌面和android版本的类库中。添加了更多源代码,因此图片更准确now@HardLuck
InternalClient
是否设置了超时或类似的设置?也许我会尝试删除所有
.ConfigureAwait(false)
代码,看看它是否有任何区别。不,它没有这样的设置,我尝试删除ConfigureAwait,结果相同。强调两点:它在doesktop上运行良好,在Xamarin上,仅从活动(而不是从库)调用PostAsync也会失败。GetAsync在任何地方都能正常工作,很高兴你找到了它。为了允许在服务调用中使用自签名证书,我建议将以下内容添加到MainActivity(或任何地方),以允许使用证书(同时注意调试语句,使其不会进入生产):
#如果DEBUG System.Net.ServicePointManager.ServerCertificateValidationCallback+=(se、cert、chain、sslError)=>返回true#endif
这就是可能的bug所在,无论我在哪里添加此事件处理程序(library\activity\etc),对于不受信任的证书,它总是被忽略。是的,我在Android上的自签名证书有很多问题,在iOS上甚至有更多问题。您可以尝试将自签名证书安装到设备/模拟器中。。。或者就像你说的那样停止使用HTTP,这可能是更容易的途径
HttpRequestMessage  request = new HttpRequestMessage(HttpMethod.Post, "/Token") { Content = formContent };
HttpResponseMessage message = await InternalClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);