大家都在尝试使用RestSharp登录我的xamarin api,如果身份验证有效,则API应该返回状态代码200 OK,如果身份验证失败(错误密码),则API返回状态代码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值 不能为null。参数名称:src“
答案 0 :(得分:4)
我终于能够找到解决方法。忍受漫长的回应。
标签提到Xamarin,这也是我正在使用的-特别是在iOS中。我认为Mono可能实际上是一个错误,但是我并没有做那么多的确认。
问题在于复制响应缓冲区的默认方式。在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,尝试查看对流不满意的地方,但我现在没有时间。
祝你好运!
答案 1 :(得分:0)
好的,所以在玩完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"];
}
}