_handler = new WebCallHandler("GetUserPath", parameters);
IEnumerator target = WaitForRequest();
_owner.StartCoroutine(target);
while (_handler.GotResult == false)
{
};
From what I have seen, if I debug the code and put a break point before the send, then step by step go through the following lines. I will get the expect result from the webservice. But, if I do not debug it, then I get a responseCode of value -1 and an empty text
It almost looks like the yield return request.Send(); does not wait for the actual return for the send before proceeding.
Can anyone tell me why this is happening?
I need reliable results from UnityWebRequest.
Why are you busy waiting in the first place?
Normally you would do it all in coroutine. Otherwise don’t use coroutine at all, just do synchronous calls to UnityWebRequest (ditch all yield resurn, do simple calls).
So I have a problem with the way the UnityWebRequest works.
Make that 2 actually.
I keep searching on the web, and I am not finding any solution for it.
First, right now when I do return request.downloadHandler.text; I get an exception
So far I cannot understand what does that. Because I changed the code to the most simple use sample for UnityWebRequest. I tested the Get link and it works perfectly.
What does that exception mean?
Second, is there a way to run the UnityWebRequest and return the result to the call parent but not through an action.
We have the same issue in Unity 5.3.6p1.
UnityWebRequest.responseCode returns -1.
We are using it for our API, see the code attached.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Experimental.Networking;
using System.Threading;
using UnityEngine;
public class API_Request
{
public delegate void ActionDelegate(API_Response response, Hashtable passedParams = null);
//Constante représentant le timeout
public const int TIMEOUT = 7;
// This is the unity web request. It's doing all the network stuff for us
public UnityWebRequest request;
//This is the response of the server. Based on DownloadHandlerScript, according to the UnityWebRequest guideline to intercept request states
private API_Response response;
public IEnumerator TimeoutProcess;
//Store the callback to pass it to the TimeOutChecker
private ActionDelegate myCallback;
public MonoBehaviour myContext;
public Hashtable myPassedParams;
public API_Request(UnityWebRequest request,MonoBehaviour context, ActionDelegate callback, Hashtable passingParams = null)
{
//Store the request
this.request = request;
//Store the callback
myCallback = callback;
myContext = context;
myPassedParams = passingParams;
TimeoutProcess = WaitForTimeout();
myContext.StartCoroutine(TimeoutProcess);
//Create a new response object
response = new API_Response(callback, this);
//Tells the unity network system that he needs to use API_Response instance to report the progress
request.downloadHandler = response;
//Send the request
request.Send();
}
//Called to retry the request
public void Retry(){
//Abort the request
request.Abort();
//Launch the timeout process again but without the authorization to retry
canRetry = false;
TimeoutProcess = WaitForTimeout();
myContext.StartCoroutine(TimeoutProcess);
//Send the request again
request.Send();
}
//Toggle that says if the request is authorized to restart
private bool canRetry;
private IEnumerator WaitForTimeout(){
yield return new WaitForSeconds(TIMEOUT);
//Retry the request
if (canRetry)
{
Retry();
}
//Invoke the callback with a 408 to signal the timeout
else {
myCallback.Invoke(new API_Response("Reached the defined timeout",API_Response.State.ERROR, 408), myPassedParams);
}
TimeoutProcess = null;
}
}
public class API_Response : DownloadHandlerScript{
//Liste des states possibles en réponse du serveur
public enum State { OK, ERROR };
private API_Request.ActionDelegate myCallback;
private List<byte> myDatas;
private API_Request myAPIRequest;
public API_Response(string responseMessage, API_Response.State state, int responseCode)
{
myDatas = new List<byte> ();
this.responseMessage = responseMessage;
this.state = state;
this.responseCode = responseCode;
}
// Standard scripted download handler - will allocate memory on each ReceiveData callback
public API_Response(API_Request.ActionDelegate callback, API_Request request) : base(){
myDatas = new List<byte> ();
myCallback = callback;
myAPIRequest = request;
}
// Pre-allocated scripted download handler
// Will reuse the supplied byte array to deliver data.
// Eliminates memory allocation.
public API_Response(byte[] buffer): base (buffer){
}
// Called once per frame when data has been received from the network.
protected override bool ReceiveData(byte[] data, int dataLength)
{
if (data == null || data.Length < 1 )
{
Debug.Log("LoggingDownloadHandler :: ReceiveData - received a null/empty buffer");
return false;
}
myDatas.AddRange(data);
Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveData - received {0} bytes", dataLength));
return true;
}
public string GetTextData(){
if(myDatas == null){
return string.Empty;
}
if (state == State.OK)
{
return System.Text.Encoding.UTF8.GetString(myDatas.ToArray());
}else{
return responseCode + " - " + System.Text.Encoding.UTF8.GetString(myDatas.ToArray());
}
}
// Called when all data has been received from the server and delivered via ReceiveData
protected override void CompleteContent()
{
ConstructResponseMessage();
Debug.Log("LoggingDownloadHandler :: CompleteContent - DOWNLOAD COMPLETE! " + myAPIRequest.request.responseCode + " MESSAGE : " + responseMessage);
if (myAPIRequest.TimeoutProcess != null)
{
myAPIRequest.myContext.StopCoroutine(myAPIRequest.TimeoutProcess);
}
if (myCallback != null)
{
myCallback.Invoke(this, myAPIRequest.myPassedParams);
}
}
public string responseMessage;
public API_Response.State state;
public int responseCode;
public void ConstructResponseMessage(){
responseCode = (int)myAPIRequest.request.responseCode;
if (myAPIRequest.request.isError)
{
Debug.Log("ERROR IN REQUEST");
state = State.ERROR;
responseMessage = " " + myAPIRequest.request.responseCode + (string.IsNullOrEmpty(myAPIRequest.request.error) == false ? " - " + myAPIRequest.request.error: "");
}
else {
Debug.Log("NO FATAL ERROR IN REQUEST");
state = myAPIRequest.request.responseCode != 200 ? State.ERROR : State.OK;
responseMessage = GetTextData();
}
}
// Called when a Content-Length header is received from the server.
protected override void ReceiveContentLength(int contentLength)
{
Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength));
}
public bool isUnauthorized()
{
if (responseCode == 401 || responseMessage.ToUpper().Contains("UNAUTHORIZED"))
{
return true;
}
return false;
}
}
public class FormContent : IMultipartFormSection
{
public string contentType
{
get
{
return "application/x-www-form-urlencoded";
}
}
public string fileName
{
get
{
return "";
}
}
public byte[] sectionData
{
get
{
return System.Text.Encoding.ASCII.GetBytes(value);
}
}
public string sectionName
{
get
{
return key;
}
}
private string key;
private string value;
public FormContent(string key, string value){
this.key = key;
this.value = value;
}
}
Do you think it’s a bug or it is something we are doing wrong ?