UnityWebRequest retusn responseCode = -1

Hi,
I am trying to use UnityWebRequest to communicate with my webservice.

static IEnumerator WaitForRequest()
{
    // https://docs.unity3d.com/Manual/UnityWebRequest.html
    string url = _url + _handler.MethodName;

    if (string.IsNullOrEmpty(_handler.Parameters) == false)
    {
        url = url + _handler.Parameters;
    }

    UnityWebRequest request = UnityWebRequest.Get(url);
    //request.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
    //request.SetRequestHeader("Pragma", "no-cache");

    yield return request.Send();
    if (request.isError)
    {
        Debug.Log("Fail " + request.error);
        _handler.Result = "failed"; //www.error;
        _handler.GotResult = true;
        yield return request.error;
    }
    else
    {
        // Extract json string
        _handler.Result = request.downloadHandler.text;
        Debug.Log("Result " + request.downloadHandler.text);
        Debug.Log("Code " + request.responseCode);
        if (string.IsNullOrEmpty(request.downloadHandler.text) == true)
        {
            _handler.Result = "empty text";
        }
        else if (string.IsNullOrEmpty(_handler.Result) == true)
        {
            _handler.Result = "Failed to set result";
        }
        _handler.GotResult = true;
        yield return request.downloadHandler.text;
    }
}

And I call this function as follow:

         _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).

But I remove the yield, will that not block the UI from refreshing other things in parallel ?

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.

        private void DoSomething()
        {
            string result = DoAWebCall();
            DoSomethingWithResult(result);
            DoSomethingElse();
        }

        private string DoAWebCall()
        {
            string result = "";

            // UnityWebRequest

            return result;
        }

        private void DoSomethingWithResult(string pResult)
        {
        }

        private void DoSomethingElse()
        {
        }

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 ?

I am not sure.
I have completely redone my code to be simpler and use Coroutines.
Now I am not having anymore problems.

This is my function for the call:

    static IEnumerator WaitForRequest(
        string pMethodName,
        string pParameters,
        CoroutineCallbackHandler pCallBack)
    {
        // https://docs.unity3d.com/Manual/UnityWebRequest.html
        string url = _url + pMethodName;

        if (string.IsNullOrEmpty(pParameters) == false)
        {
            url = url + pParameters;
        }

        UnityWebRequest www = UnityWebRequest.Get(url);
        yield return www.Send();

        Dictionary<string, object> results = new Dictionary<string, object>();
        if (www.isError)
        {
            yield return www.error;

            results.Add("success", false);
            results.Add("errorMessage", www.error);
        }
        else
        {
            // Show results as text
            yield return www.downloadHandler.text;

            string result = www.downloadHandler.text;
            Debug.Log(result);
            int indexA = result.IndexOf("{");
            int indexB = result.IndexOf("[");
            string startsWith = "{";
            string endsWith = "}";
            if (indexB > 0 && indexB < indexA)
            {
                startsWith = "[";
                endsWith = "]";
            }
            result = result.Substring(result.IndexOf(startsWith)) + 1;
            result = result.Substring(0, result.LastIndexOf(endsWith) + 1);

            results.Add("success", true);
            results.Add("data", result);
        }

        pCallBack.Results = results;
        pCallBack.Call();
    }