Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RestSharp";获取响应流(ReadAsync)时出错:ReceiveFailure值不能为null。参数名称:src";_C#_Api_Xamarin.forms_Restsharp - Fatal编程技术网

C# RestSharp";获取响应流(ReadAsync)时出错:ReceiveFailure值不能为null。参数名称:src";

C# RestSharp";获取响应流(ReadAsync)时出错:ReceiveFailure值不能为null。参数名称:src";,c#,api,xamarin.forms,restsharp,C#,Api,Xamarin.forms,Restsharp,大家好,我正在尝试使用RestSharp登录我的xamarin api,如果身份验证有效,api应该返回状态代码200 OK,如果身份验证失败,则返回状态代码415(密码错误),根据案例场景的不同,返回其他代码,但当身份验证通过时,我在所有其他案例旁侧获得状态代码0(状态代码200 ok),下面的源代码是我如何实现的 //payload am sending to the api RequestPayload res = new RequestPayload(); res.appi

大家好,我正在尝试使用RestSharp登录我的xamarin api,如果身份验证有效,api应该返回状态代码200 OK,如果身份验证失败,则返回状态代码415(密码错误),根据案例场景的不同,返回其他代码,但当身份验证通过时,我在所有其他案例旁侧获得状态代码0(状态代码200 ok),下面的源代码是我如何实现的

 //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
        }
在所有场景中,它返回一个状态码:0、内容类型:、内容长度:0)和错误消息

获取响应流(ReadAsync)时出错:ReceiveFailure值 不能为空。参数名称:src“

下面的屏幕截图指示api调用失败的时间 验证有效时收到的响应

我终于找到了解决办法。忍受冗长的回答

标签上提到了Xamarin,这也是我正在使用的——特别是iOS。我认为这实际上可能是Mono的一个bug,但我没有花那么多的时间来证实

问题在于复制响应缓冲区的默认方式。在RestSharp代码中,这是由MiscExtensions.cs中名为ReadAsBytes的扩展方法完成的。似乎对于某些响应缓冲区,对Stream.Read方法的调用失败。发生这种情况时,异常会导致RestSharp“快捷”响应上的其余处理,因此状态代码永远不会被填充,因为它发生在调用ReadAsBytes之后

好消息是RestSharp确实提供了一种方法,用您自己的调用替换对ReadAsBytes的调用。这是通过IRestRequest对象上的ResponseWriter属性完成的。如果它定义了一个函数,它将绕过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的其他方法,但在我的例子中,这是我们唯一使用的方法,所以它就足够了

到目前为止,这似乎对我有好处。也许如果有人有雄心壮志,他们可以把它一直追踪到Mono,看看它对这条流有什么不喜欢,但我现在没有时间


祝你好运

好吧,在玩了一会儿RestSharp之后,我意识到正如@steve_In_之前提到的那样,MONO存在兼容性问题(我们认为这是一个bug),所以我使用.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"];
            }
    }

这里有一个类似的问题。可能你可以参考Ankeysteve,我已经看到了这个问题,但是,解决方案对我不起作用,如果服务器发送任何其他响应,我的问题就会发生。我有一个类似的问题,有401个错误。如果为所有异常启用break,您可以看到RestSharp中有几个异常被抛出,但它们没有冒泡,状态代码最终为零。在我的例子中,401上返回的响应是纯文本“expired”而不是json,这让我相信它与解析器有关,但它甚至从未命中OnBeforeDeserialization方法,因此似乎排除了解析错误。从最初的511开始,服务器指示auth expired,随后的401指示我有一个坏密钥(因为我不知道511来了,需要更新),我得到了同样的错误条件。但是我确实点击了OnBeforeDeserialization方法,并且已经抛出了异常,所有响应数据都丢失了,包括标题和状态代码……你好,steve我尝试了您的解决方案,它不起作用,而是出现了错误“获取响应流时出错(ReadAsync):ReceiveFailure值不能为null。参数名称:src”它仍然会抛出错误,但catch将允许它继续并完成填充响应对象,这样您至少可以返回状态代码。也发现了这个。看起来这确实可能是Mono的一个问题。我遇到了一些没有通过ResponseWriter的其他场景,但最终仍然返回零状态代码,因此显然这不是一个完整的解决方案。我还没来得及追查,看看是否能找到解决这些问题的办法。我在上面看到的一个错误是“连接被对等方关闭”。嗨,Steve,我使用了另一个.net http客户端来实现这个结果,我在下面的答案中有实现,谢谢你的帮助。我根本不明白这是如何工作的,正如你在最初的问题中所建议的,当内容为null(len=0)时问题会出现在您的解决方案中,您反序列化null,然后继续使用它。在我看来,反序列化空值似乎很累,但却失败了。您的解决方案甚至比OP更糟糕。请告知Hello axa,我感兴趣的是响应的内容,即(response.content),但如果我的登录请求失败,并且我得到的状态代码与200不同,则response.content将为空(我不会从后端获得原始响应)