RestSharp "Ошибка при получении потока ответов (ReadAsync): значение ReceiveFailure не может быть нулевым. Имя параметра: src" - PullRequest
0 голосов
/ 19 сентября 2018

Привет всем, я пытаюсь выполнить вход в мой xamarin api с помощью RestSharp, API должен вернуть код состояния 200 OK, если аутентификация работает, и код состояния 415, если аутентификация не удалась (неправильный пароль), и другие коды в зависимости от того, чтосценарий случая, но вместо этого я получаю код состояния 0 во всех других случаях, кроме случая, когда проходит аутентификация (код состояния 200 в порядке), приведенный ниже исходный код показывает, как я реализую

 //payload am sending to the api
   RequestPayload res = new RequestPayload();
   res.appid = appid;
   res.data = data;
   res.method = "Login";

   //convert to json object
   var MySerializedObject =  JsonConvert.SerializeObject(res);
   string APIUrl = ""http://142.168.20.15:8021/RouteTask";

   //create client
   RestClient client = new RestClient(APIUrl);

   //create request
   RestRequest request = new RestRequest(Method.POST);

   // set request headeer
   request.AddHeader("Content-Type", "application/x-www-form-urlencoded");

   //request.AddJsonBody(MySerializedObject); --i have also tried this

   request.AddParameter("application/json", MySerializedObject, ParameterType.RequestBody);
   request.JsonSerializer.ContentType = "application/json; charset=utf-8";
   request.AddParameter("RequestSource", "Web", "application/json", ParameterType.QueryString);
   client.Timeout = 2000000;
   var response =  client.Execute(request); // where the issue appears
   //RestResponse response =  client.Execute(request); // i have tried this
   //IRestResponse response =  client.Execute(request); // i have tried this
    if (response.IsSuccessful)
        {
         //use response data
        }

на всех сценариях, которые он возвращаетс StatusCode: 0, Content-Type:, Content-Length: 0) и errorMessage

"Ошибка при получении потока ответа (ReadAsync): значение ReceiveFailure не может быть нулевым. Имя параметра: src"

скриншот ниже показывает, когда произошел сбой вызова API enter image description here Ответ получен, когда аутентификация действительна Success Authentication

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

ОК, поэтому, немного поиграв с RestSharp, я понимаю, что, как @steve_In_Co упомянул ранее, были проблемы с совместимостью с MONO (мы предполагаем, что это ошибка), поэтому я сделал это простым способом, используя HTTP-библиотеку .Net.и это работает для меня, поэтому, если кто-то все еще ищет выход, найдите рабочий код реализации .net http ниже.

//payload am sending to the api 
   RequestPayload res = new RequestPayload();
   res.appid = appid;
   res.data = data;
   res.method = "Login";

   //convert to json object
   var MySerializedObject =  JsonConvert.SerializeObject(res);

   string APIUrl = ""http://142.168.20.15:8021/RouteTask";

   //create basic .net http client
   HttpClient client = new HttpClient();
   client.BaseAddress = new Uri(APIUrl);

   // this was required in the header of my request, 
   // you may not need this, or you may need to adjust parameter
   //("RequestSource","Web") or you own custom headers
   client.DefaultRequestHeaders.Add("RequestSource", "Web");
    // this class is custom, you can leave it out
   connectionService = new ConnectionService();
  //check for internet connection on users device before making the call
  if (connectionService.IsConnected)
    {
       //make the call to the api
        HttpResponseMessage response = await 
        client.PostAsJsonAsync(ApiConstants.APIDefault, res);
        if (response.IsSuccessStatusCode)
            {
                string o = response.Content.ReadAsStringAsync().Result;
                dynamic payload = JsonConvert.DeserializeObject(o);
                string msg = payload["valMessage"];
                resp.a = true;
                resp.msg = payload["responseDescription"];
            }
        else
            {
                string o = response.Content.ReadAsStringAsync().Result;
                dynamic payload = JsonConvert.DeserializeObject(o);
                resp.a = false;
                resp.msg = payload["response"];
            }
    }
0 голосов
/ 27 сентября 2018

Я наконец смог найти обходной путь для этого.Имейте в виду многословный ответ.

В тегах упоминается Xamarin, над которым я тоже работаю - особенно с iOS.Я думаю, что это может быть ошибка с Mono, но я не зашел так далеко, чтобы подтвердить.

Проблема заключается в способе копирования буфера ответов по умолчанию.В коде RestSharp это выполняется методом расширения в MiscExtensions.cs, который называется ReadAsBytes.Похоже, что при определенных буферах ответа вызов метода Stream.Read не выполняется.Когда это происходит, исключение заставляет RestSharp «сокращать» остальную часть обработки ответа, поэтому код состояния никогда не заполняется, поскольку это происходит после вызова ReadAsBytes.

Хорошая новость заключается в том, что RestSharp делаетдать способ заменить этот вызов ReadAsBytes одним из ваших собственных.Это делается с помощью свойства ResponseWriter объекта IRestRequest.Если у него есть определенная функция, он пропустит вызов ReadAsBytes и вызовет функцию, которую вы ей дали.Проблема в том, что это определяется как Действие, и вы не получаете копию объекта полного ответа, так что это несколько бесполезно.Вместо этого вы должны использовать свойство AdvancedResponseWriter.Этот включает в себя как объект ответа и поток ответа.Но вам все равно нужно установить свойство ResponseWriter, иначе оно не будет обходить обработчик по умолчанию, и вы все равно получите сообщение об ошибке.

Хорошо, так как вы это сделаете?В итоге я реализовал его как обертку для RestClient, чтобы мне не пришлось реализовывать код повсюду.Вот базовая настройка:

public class MyRestClient : RestClient
{
    public MyRestClient(string baseUrl) : base(baseUrl)
    { }

    public override IRestResponse Execute(IRestRequest request)
    {
        request.ResponseWriter = s => { };
        request.AdvancedResponseWriter = (input, response) => response.RawBytes = ReadAsBytes(input);

        return base.Execute(request);
    }

    private static byte[] ReadAsBytes(Stream input)
    {
        var buffer = new byte[16 * 1024];

        using (var ms = new MemoryStream())
        {
            int read;
            try
            {
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                { ms.Write(buffer, 0, read); }

                return ms.ToArray();
            }
            catch (WebException ex)
            { return Encoding.UTF8.GetBytes(ex.Message); }
        };
    }
}

Метод ReadAsBytes на самом деле является просто копированием / вставкой метода RestSharp ReadAsBytes с добавлением try / catch.Если происходит сбой, он возвращает причину исключения в буфер ответов.Это может или не может быть то, что вы хотите, поэтому измените по мере необходимости.Вам также может понадобиться переопределить другие методы для Execute, но в моем случае это единственный используемый нами метод, поэтому этого было достаточно.

Пока что, похоже, это помогает мне.Возможно, если кто-то станет честолюбивым, он сможет проследить его до Моно, чтобы попытаться увидеть, что ему не нравится в потоке, но у меня нет времени на это в данный момент.

Хорошоудачи!

...