簡體   English   中英

RestSharp“獲取響應流時出錯(ReadAsync):ReceiveFailure Value不能為null。參數名稱:src“

[英]RestSharp “Error getting response stream (ReadAsync): ReceiveFailure Value cannot be null. Parameter name: src”

大家好我正在嘗試使用RestSharp登錄我的xamarin api,API應該返回狀態代碼200 OK如果驗證工作,狀態代碼415如果驗證失敗(密碼錯誤)和其他代碼取決於具體情況,但是,當身份驗證通過時(狀態代碼200 ok),我在所有其他情況下獲得狀態代碼0,下面的源代碼是我如何實現的

 //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
        }

在所有的scenerio上它返回一個StatusCode:0,Content-Type :, Content-Length:0)和errorMessage

“獲取響應流時出錯(ReadAsync):ReceiveFailure Value不能為null。參數名稱:src”

下面的截圖表明api調用何時失敗 在此輸入圖像描述 驗證有效時收到響應 成功驗證

我終於能夠為此找到解決方法。 忍受冗長的回應。

標簽提到Xamarin,這也是我正在使用的 - 特別是iOS。 我認為它可能實際上是Mono的一個錯誤,但我沒有把它當作確認。

問題在於復制響應緩沖區的默認方式。 在RestSharp代碼中,這是通過MiscExtensions.cs中名為ReadAsBytes的擴展方法完成的。 看來,對於某些響應緩沖區,對Stream.Read方法的調用失敗。 發生這種情況時,異常會導致RestSharp“快捷”處理響應的其余處理,因此狀態代碼永遠不會被填充,因為它在調用ReadAsBytes之后發生。

好消息是RestSharp確實提供了一種方法來將ReadAsBytes替換為您自己的一個。 這是通過IRestRequest對象上的ResponseWriter屬性完成的。 如果它定義了一個函數,它將繞過ReadAsBytes調用並調用你給它的函數。 問題是,這被定義為一個Action,你沒有獲得完整響應對象的副本,所以它有點無用。 相反,您必須使用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的其他方法,但在我的情況下,這是我們使用的唯一方法,因此它就足夠了。

到目前為止,這似乎是為我做的伎倆。 也許如果有人雄心勃勃,他們可以一直追蹤到Mono,試着看看它對流不喜歡什么,但我現在沒有時間。

祝好運!

好的,所以在使用RestSharp玩了一下后,我意識到正如前面提到的@steve_In_Co一樣,MONO存在兼容性問題(我們認為這是一個錯誤)所以我使用.Net HTTP庫以基本方式完成它並且它可以工作對我來說,如果有人仍在尋找出路,請在下面找到工作的.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"];
            }
    }

暫無
暫無

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

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