2016-05-28 4 views
2

У меня есть кусок кодаHttpClient PostAsync на Xamarin ничего не делает

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 из-за таймаута.

+0

1) Что именно вы подразумеваете под словом "fail"? 2) Существуют ли какие-либо различия в сумме cal для этого метода? –

+0

не работает, я имею в виду, что он выдает исключение и никогда не попадает на сервер. Не проверял diff стека вызовов - он находится только в той же библиотеке классов, которую я использую для настольных и Android-версий. – HardLuck

+0

добавлено больше исходного кода, поэтому изображение более точно сейчас – HardLuck

ответ

1

Для всех борется с той же проблемой - это связано с SSL (самоподписывающемуся CERT в моем случае). Если вы пытаетесь подключиться к вашему серверу через HTTPS - сначала попробуйте использовать простой HTTP, мое приложение может работать с HTTP штрафом, пока HTTPS зависает до смерти.

+0

Рад, что вы это поняли. Чтобы разрешить самозаверяющие сертификаты в вызовах службы, я бы предложил добавить следующее в вашу MainActivity (или где угодно), которая позволит сертификатам (также отмечая операторы DEBUG, чтобы они не вносили его в производство): '#if DEBUG System .Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslError) => return true; # endif' – hvaughan3

+0

, где может быть возможная ошибка, независимо от того, где я добавляю этот обработчик событий (library \ activity \ etc), он всегда игнорируется для ненадежных сертификатов. – HardLuck

+0

У меня было много проблем с самоподписанными сертификатами на Android и даже больше на iOS. Вы можете попробовать установить самозаверяющий сертификат в устройство/эмулятор ... или просто прекратить использование HTTP, как вы сказали, что может быть проще – hvaughan3

0

У меня были и другие проблемы с PostAsync(), и это также не так настраивается, как SendAsync() с точки зрения редактирования заголовков и тому подобного. Я бы порекомендовал SendAsync():

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

Неудачно SendAsync с 'HttpMethod.Post' ведет себя так же – HardLuck

+0

@HardLuck Тогда это должно быть проблемой где-то в другом месте, потому что это отлично работает для меня. Возможно, напишите больше кода, чтобы узнать, в чем проблема. – hvaughan3

+0

Может быть, я добавлю еще код, тогда – HardLuck

Смежные вопросы