c# - RestSharp "Error getting response stream (ReadAsync): ReceiveFailure Value cannot be null. Parameter name: src"

标签 c# api xamarin.forms restsharp

大家好,我正在尝试使用 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
        }

在所有情况下,它都会返回 StatusCode: 0, Content-Type: , Content-Length: 0) 和 errorMessage

"Error getting response stream (ReadAsync): ReceiveFailure Value cannot be null. Parameter name: src"

下面的截图显示了 api 调用失败的时间 enter image description here 身份验证有效时收到的响应 Success Authentication

最佳答案

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

标签提到了 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 以尝试查看流不喜欢什么,但我目前没有时间。

祝你好运!

关于c# - RestSharp "Error getting response stream (ReadAsync): ReceiveFailure Value cannot be null. Parameter name: src",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52402634/

相关文章:

javascript - 在 javascript 变量中使用来自发布请求的结果

Python:显示为列表 httplib.HTTPMessage 时出现问题

xamarin - 将 android 项目引用到 ui 测试项目 Xamarin 时出错

c# - 使用 Xamarin Forms 在 Android 上快速隐藏和重新出现键盘

c# - 通过 PCL 创建 MVVM Light ViewModel?适用于 Xamarin.Forms 和 WPF

c# - Linkedin API(授权 token (oauth2))c#.net

C# 从 App.xaml.cs 访问 WPF 主窗口中的静态属性时导致这种奇怪行为的原因

ios - swift API认证

c# - 使用任务并行库的更好方法是什么

c# - streamreader 读取 xml 文件,然后 file.move 移动 xml 文件 - c#