Search Unity

  1. Unity 2020.2 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Call API using Web GL

Discussion in 'Scripting' started by mholmes, Jan 13, 2021.

  1. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Not sure what's going on but I have working code for a desktop app/mobile app I'm trying to port to WebGL. Upon testing the WebGL is not making calls to the API. Its almost like its unable to send the object.

    API Backend:
    Code (CSharp):
    1. [Route("api/WhiteBoXGaming/Post_TestAPI")]
    2.         [HttpPost]
    3.         public WBGString WhiteBoxGaming_Test([FromBody]OAuth oAuth)
    4.         {
    5.             bool AccessGranted = _DataHelper.OAuth(oAuth.Administrator, oAuth.Password);
    6.             WBGString WBGString = new WBGString();
    7.  
    8.             if (AccessGranted)
    9.             {
    10.                 WBGString.Http_Response = "White Box Gaming Established 2018 All Rights Reserved";              
    11.             }
    12.             else
    13.             {
    14.                 WBGString.Http_Response = "Access Denied";
    15.             }
    16.  
    17.             return WBGString;
    18.         }
    Client/App
    Code (CSharp):
    1. using Newtonsoft.Json;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.IO;
    6. using System.Net;
    7. using System.Net.Http;
    8. using UnityEngine;
    9. using UnityEngine.UI;
    10. using WBG_4;
    11.  
    12. public class send : MonoBehaviour
    13. {
    14.     public Text txtResponse;
    15.  
    16.     private string _Response;
    17.  
    18.     public void Send()
    19.     {
    20.         string uri = WBG_Config._EndPoint + "api/WhiteBoXGaming/Post_TestAPI";
    21.         OAuth oAuth = new OAuth();
    22.  
    23.         oAuth.Administrator = WBG_Config._OAuth_Admin;
    24.         oAuth.Password = WBG_Config._OAuth_Password;
    25.  
    26.         StartCoroutine(Testwebrequest(uri, oAuth));
    27.  
    28.         txtResponse.text = _Response;
    29.     }
    30.  
    31.     IEnumerator Testwebrequest(string uri, object obj)
    32.     {
    33.         string json = JsonConvert.SerializeObject(obj);
    34.         var client = new HttpClient();
    35.         var webRequest = WebRequest.Create(uri);
    36.         webRequest.Method = "POST";
    37.         webRequest.ContentType = "application/json";
    38.  
    39.         using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
    40.         {
    41.             streamWriter.Write(json);
    42.         }
    43.  
    44.         var httpResponse = (HttpWebResponse)webRequest.GetResponse();
    45.         using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
    46.         {
    47.             var result = streamReader.ReadToEnd();
    48.             _Response = Convert.ToString(result);
    49.         }
    50.  
    51.         yield return _Response;
    52.     }
    53. }
    54.  
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    4,805
    Debug and figure out what's happening. Is the code even running? Is the request getting to the server? Is there an error coming back from the server? What kind of error is coming back from the server?
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    10,990
    This... but since it's a browser problem the first culprit is likely CORS.
     
    PraetorBlue likes this.
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    10,990
    Also, open the browser debug window and look for exceptions.
     
  5. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Its never making it to the API. I have the API running locally for testing. I assume this code is not right or at least not how WebGL interacts with http request to an api. Thats the part i dont know. If someone has a working snipett of how to send a http request to an api using webgl that would likely help.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    10,990
    I always use UnityWebRequest.

    Reason: it works.

    Good luck!
     
    Suddoha likes this.
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    4,805
    Are you testing in a web browser? Have you tried using your browser's developer tools to see what happens with the request? I suspect @Kurt-Dekker 's theory about CORS is probably correct.
     
  8. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    @Kurt-Dekker
    I'm trying to convert my code to use the Unity Web Request as suggested but keeps sending null. What did I do wrong here?

    Code (CSharp):
    1. IEnumerator TestUnityWebRequest(string uri, object obj)
    2.     {
    3.         string json = JsonConvert.SerializeObject(obj);
    4.  
    5.         UnityWebRequest www = UnityWebRequest.Post(uri, json);
    6.         yield return www.SendWebRequest();
    7.  
    8.         if (www.isNetworkError || www.isHttpError)
    9.         {
    10.             Debug.Log(www.error);
    11.         }
    12.         else
    13.         {
    14.             Debug.Log("Sent");
    15.         }
    16.     }
     
  9. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Tried this as well but still failed:
    Code (CSharp):
    1.  private IEnumerator Testwebrequest2(string uri, object obj)
    2.     {
    3.         string json = JsonConvert.SerializeObject(obj);
    4.         var request = UnityWebRequest.Post(uri, json);
    5.  
    6.         request.SetRequestHeader("Content-Type", "application/json");
    7.  
    8.         yield return request.SendWebRequest();
    9.  
    10.         if (request.isNetworkError || request.isHttpError)
    11.         {
    12.             Debug.Log(request.error);
    13.         }
    14.         else
    15.         {
    16.             Debug.Log("Sent");
    17.         }
    18.  
    19.         yield return request;
    20.     }

    Can some one please convert my working request to Unity Web Request Please. Thanks
     
  10. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I got the request working now I need to get the response converted to a Object:

    Code (CSharp):
    1. IEnumerator Post(string url, string bodyJsonString)
    2.     {
    3.         var request = new UnityWebRequest(url, "POST");
    4.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    5.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    6.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    7.         request.SetRequestHeader("Content-Type", "application/json");
    8.  
    9.         yield return request.Send();
    10.        
    11.         Debug.Log("Status Code: " + request.responseCode);
    12.  
    13.         var response = request.downloadHandler.text;
    14.         using (var streamReader = new StreamReader(response))
    15.         {
    16.             var result = streamReader.ReadToEnd();
    17.             _Response = Convert.ToString(result);
    18.         }
    19.  
    20.         yield return _Response;
    21.  
    22.  
    23.  
    24.         txtResponse.text = request.ToString();
    25.     }
    getting illegal character error
     
  11. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Figured it out. After a lot of trial and error here is working code sample:

    Code (CSharp):
    1. IEnumerator Post(string url, string bodyJsonString)
    2. {
    3.     var request = new UnityWebRequest(url, "POST");
    4.     byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    5.     request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    6.     request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    7.     request.SetRequestHeader("Content-Type", "application/json");
    8.  
    9.     yield return request.Send();
    10.    
    11.     Debug.Log("Status Code: " + request.responseCode);
    12.  
    13.     var response = request.downloadHandler.text;
    14.     using (var streamReader = new StreamReader(response))
    15.     {
    16.         var result = streamReader.ReadToEnd();
    17.         _Response = Convert.ToString(result);
    18.     }
    19.  
    20.     yield return _Response;
    21.  
    22.  
    23.  
    24.     txtResponse.text = request.ToString();
    25. }
     
  12. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    4,805
    You don't need line 20, it doesn't really do anything except wait an extra frame for no reason.
     
    Bunny83 likes this.
  13. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I got the Unity Web Request working but its still not working when I test outside of the editor. Please here is the call:

    Code (CSharp):
    1. using Newtonsoft.Json;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Data;
    6. using System.IO;
    7. using System.Net;
    8. using System.Net.Http;
    9. using System.Runtime.Serialization.Formatters.Binary;
    10. using System.Text;
    11. using UnityEngine;
    12. using UnityEngine.Networking;
    13. using UnityEngine.UI;
    14. using WBG_4;
    15.  
    16. public class send : MonoBehaviour
    17. {
    18.     public Text txtResponse;
    19.  
    20.     private string _Response;
    21.  
    22.     public void Send()
    23.     {
    24.         string uri = WBG_Config._EndPoint + "api/WhiteBoXGaming/Post_TestAPIJson"; //"api/WhiteBoXGaming/Post_TestAPI";//
    25.         OAuth oAuth = new OAuth();
    26.  
    27.         oAuth.Administrator = WBG_Config._OAuth_Admin;
    28.         oAuth.Password = WBG_Config._OAuth_Password;
    29.  
    30.         string json = JsonConvert.SerializeObject(oAuth);
    31.  
    32.         StartCoroutine(Post(uri, json));
    33.     }
    34.  
    35.     IEnumerator Post(string url, string bodyJsonString)
    36.     {
    37.         var request = new UnityWebRequest(url, "POST");
    38.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    39.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    40.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    41.         request.SetRequestHeader("Content-Type", "application/json");
    42.  
    43.         yield return request.Send();
    44.        
    45.         Debug.Log("Status Code: " + request.responseCode);
    46.  
    47.         var response = request.downloadHandler.data;
    48.         string json = System.Text.Encoding.UTF8.GetString(response);
    49.         var _Response = JsonConvert.DeserializeObject<string>(json);
    50.  
    51.         yield return _Response;
    52.  
    53.         txtResponse.text = _Response;
    54.     }
    55. }
    I'm testing locally using Firefox not sure if that makes a difference. It works in the Unity editor but out side of that it fails.
     
  14. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I also just tried this way and still not working. Does anyone have working WebGL that can make calls to an API?

    Code (CSharp):
    1.  IEnumerator GetJsonContent(string url, string bodyJsonString)
    2.     {
    3.         var request = UnityWebRequest.Post(url, "{}");
    4.         request.method = "POST";
    5.  
    6.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    7.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    8.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    9.         request.SetRequestHeader("Content-Type", "application/json");
    10.  
    11.         yield return request.SendWebRequest();
    12.  
    13.         while (!request.isDone)
    14.         {
    15.             yield return new WaitForEndOfFrame();
    16.         }
    17.  
    18.         if (request.isNetworkError)
    19.         {
    20.             Debug.Log(request.error);
    21.         }
    22.         else
    23.         {
    24.             //var jsonContent = request.downloadHandler.text;
    25.  
    26.             var response = request.downloadHandler.data;
    27.             string json = System.Text.Encoding.UTF8.GetString(response);
    28.             var _Response = JsonConvert.DeserializeObject<string>(json);
    29.  
    30.             txtResponse.text = _Response;
    31.         }
    32.  
    33.         yield break;
    34.     }
     
  15. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    521
    Well, we don't know where your WebGL content is hosted and if the API belongs to the same domain. If not the server that serves the API does not implement CORS, your browser will not allow any cross domain requests.

    Note that browsers like Chrome and FireFox usually restrict locally (file hosted) webcontent even more. There are some configuration flags that can be changed in the browsers to allow local file testing. If you want to test your webgl application I highly recommend that you use an actual web server to host your content.

    So first you should check if you are crossing domain borders and if you do, make sure the API server allows access from your domain (it's possible to allow any domain for that matter).
     
  16. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I have a web host I could use did not want to put it on there until i tested locally. So if your saying this should work then i'll put it on there just to test
     
  17. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    @Bunny83 so your saying you do all your best testing in prod right lol jk
     
  18. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    521
    No ^^ Testing can be done locally. However you should test it on a real server. Commonly you could simply install XAMPP or a similar package depending on your needs. Not related to Unity development but for some other business project I maintain I have setup some local fake domains in my windows's hosts file so I can actually register SSL certs localls to actually test everything well to the bone locally.

    It's still not clear if the API you are trying to reach actually belongs to your own server or if it's a third party service. If it's part of your own server, you can run that API also locally on your test server. The application I maintain uses a PHP backend with a MySql database. It's an ancient Zend based application -.-.

    Apart from that Xampp server which I only boot up when I'm actually working on that project, I also have an apache server on my raspberry pi running in my home network which is actually reachable from the internet. So I can test certain APIs even from the internet. Though I mainly use the webserver on my pi to host my computercraft scripts so i have them available no matter on which server I play minecraft :p
     
  19. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    @mholmes You'll need to define "not working", how are you debugging? Is your web server receiving the request? Is this code actually executing? All this can be determined with Debug.Log statements, provide your output here. In my apps, I simply write the debug output to a UI Text element during development. You can also use Charles Proxy to monitor the actual networks requests for debugging

    Code (CSharp):
    1.  private void MyDebug(string debug)
    2.     {
    3.        
    4.         Debug.Log(debug);
    5.         myText.text += "\r\n" + debug;
    6.     }
    https://support.unity.com/hc/en-us/articles/115002917683-Using-Charles-Proxy-with-Unity

    https://forum.unity.com/threads/tips-for-new-unity-users.701864/#post-5057741

    https://docs.unity3d.com/Manual/webgl-debugging.html
     
  20. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    So I was right it does not work, I uploaded to my site and still not working. So does anyone have a sample code where you make calls to a working API using WebGL?
     
  21. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    As mentioned, define "not working". How are you debugging? What is the return code from request.SendWebRequest, for example. You'll want to Debug.Log this value.
     
  22. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Are you guys reading all the post or just the last post? There is a huge history explaining the issues I'm having.

    Update:
    I have one final test I can do before I'm out of ideas on this issue
     
    Last edited: Jan 14, 2021
  23. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    Personally I've been following the entire thread. You haven't confirmed if your code is actually executing, nor the if the web server is receiving the requests. Several persons have recommended that you debug your code, but I haven't seen any debug output yet. When debugging an API, you always check the API method return code. "Not working" could mean that your code isn't executing, or is executing and failing, please confirm with the debug output.
     
    Kurt-Dekker and PraetorBlue like this.
  24. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Sorry for delay on responses. I'm debugging by break points both on a local API and in app. The API is a known working API. I have a prod version as well I'm testing with as well. I've never used Unity Web Request. Only used HTTP, so Unity Web Request is new to me. Just trying to understand how it works in editor and on a desktop app built but not on Web GL. Right now I'm uploading it to my prod web server for more testing. After this im out of ideas on how to debug or even fix.
     
  25. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Thats fair. So original issue was it was not reaching the API. That got fixed. Issue 2 was it was returning but I di dnot know how to convert the returned from byte array into object. That got fixed and now I'm working on testing on a "built" WebGL version. Prior all testing was in Unity Editor. I hope that makes sense. Anyway now I'm posting the "built" webGl code on the hosted prod server for more testing to see if it will work since it was suggested locally testing via browser is likely the issue.
     
  26. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    What is the return code from request.SendWebRequest? That will likely tell you the issue, my guess is 403-Unauthorized.
     
  27. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    So here is the website testing on http://www.whiteboxgaming.com/webgl/ Its still not working. Here is the code:
    Code (CSharp):
    1. using Newtonsoft.Json;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Data;
    6. using System.IO;
    7. using System.Net;
    8. using System.Net.Http;
    9. using System.Runtime.Serialization.Formatters.Binary;
    10. using System.Text;
    11. using UnityEngine;
    12. using UnityEngine.Networking;
    13. using UnityEngine.UI;
    14. using WBG_4;
    15.  
    16. public class send : MonoBehaviour
    17. {
    18.     public Text txtResponse;
    19.     public Text txtDebug;
    20.  
    21.     private string _Response;
    22.  
    23.     public void Send()
    24.     {
    25.         string uri = WBG_Config._EndPoint + "api/WhiteBoXGaming/Post_TestAPI";
    26.         OAuth oAuth = new OAuth();
    27.  
    28.         oAuth.Administrator = WBG_Config._OAuth_Admin;
    29.         oAuth.Password = WBG_Config._OAuth_Password;
    30.  
    31.         string json = JsonConvert.SerializeObject(oAuth);
    32.  
    33.         //StartCoroutine(Post(uri, json));
    34.         StartCoroutine(GetJsonContent(uri, json));
    35.     }
    36.  
    37.     IEnumerator Post(string url, string bodyJsonString)
    38.     {
    39.         var request = new UnityWebRequest(url, "POST");
    40.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    41.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    42.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    43.         request.SetRequestHeader("Content-Type", "application/json");
    44.  
    45.         txtDebug.text = request.ToString();
    46.  
    47.         yield return request.Send();
    48.      
    49.         Debug.Log("Status Code: " + request.responseCode);
    50.  
    51.         var response = request.downloadHandler.data;
    52.         string json = System.Text.Encoding.UTF8.GetString(response);
    53.         var _Response = JsonConvert.DeserializeObject<string>(json);
    54.  
    55.         yield return _Response;
    56.  
    57.         txtResponse.text = _Response;
    58.     }
    59.  
    60.     IEnumerator GetJsonContent(string url, string bodyJsonString)
    61.     {
    62.         var request = UnityWebRequest.Post(url, "{}");
    63.         request.method = "POST";
    64.  
    65.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    66.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    67.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    68.         request.SetRequestHeader("Content-Type", "application/json");
    69.  
    70.         yield return request.SendWebRequest();
    71.  
    72.         while (!request.isDone)
    73.         {
    74.             yield return new WaitForEndOfFrame();
    75.         }
    76.  
    77.         if (request.isNetworkError)
    78.         {
    79.             Debug.Log(request.error);
    80.         }
    81.         else
    82.         {
    83.             //var jsonContent = request.downloadHandler.text;
    84.  
    85.             var response = request.downloadHandler.data;
    86.             string json = System.Text.Encoding.UTF8.GetString(response);
    87.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    88.  
    89.             txtResponse.text = _Response.Http_Response;
    90.         }
    91.  
    92.         yield break;
    93.     }
    94. }
    95.  
    I have no way of debugging when its on live server.


    Update:
    I'll try to get return code let me update code

    Update
    well now it looks like its never even calling the co routine
     
    Last edited: Jan 14, 2021
  28. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    4,805
    If you just use your browser developer tools, you can see the errors:
    upload_2021-1-14_16-36-33.png
     
  29. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    Yes, you can debug on a live web server, I provided instructions previously. And I might recommend to create a "Hello Web Server" sample project to isolate your issue. Don't use a co-routine, just use a simple button click.
     
  30. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
  31. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    You don't need browser tools to debug, following previous instructions. But they both provide the same output.
     
    PraetorBlue likes this.
  32. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    @JeffDUnity3D I assume you know the answer to this then. According to stack overflow the issue I have is because Newtonsoft and IL2CPP. It looks like the new versions of Newtonsoft are supported for 2018 and higher? I know I'm using a old version. Do you know what version supports IL2CPP?
     
  33. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    You are having JSON errors? I thought you were having web request errors. So the server is returning a response? You need to provide the results of your debugging rather than this back and forth. I don't know the "the issue I have" that you refer to.
     
  34. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    @JeffDUnity3D I literally just learned that the issue is JSon. @PraetorBlue pointed it out to me so I tested and they where right. Its a Json issue with IL2CPP. So Now I'm asking what version of Newtonsoft works with IL2CPP? Just a part of the troubleshooting process.

    Edit:
    it says latest version is Version 12.0.3. Will that work with IL2CPP?
     
  35. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    Try it and see? What is the error that you receiving? I would not want to guess at a specific recommendation without knowing the cause and the error. Take JSON out of the equation, just use text during testing and simplify your problem. Otherwise, JSON.NET is a good choice.
     
  36. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I'm going to update the server API but here is what I get error wise from browser:

    Code (CSharp):
    1. NotSupportedException: System.Reflection.Emit.DynamicMethod::.ctor
    2.  
    3. (Filename: currently not available on il2cpp Line: -1)
    4.  
    5. 4252c009-27c1-44f6-b9df-3078cec7e1f8:8:48377
    6.     _JS_Log_Dump blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    7.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1581907
    8.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1585629
    9.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1584803
    10.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1578799
    11.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1639944
    12.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:5137826
    13.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:12267550
    14.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:12267627
    15.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:6172720
    16.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:12281307
    17.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:6172720
    18.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:12249823
    19.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:9280937
    20.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7138827
    21.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7166637
    22.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7171514
    23.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7170144
    24.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7168640
    25.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7167941
    26.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:6173168
    27.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:7143175
    28.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:8604910
    29.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:14515265
    30.     dynCall_iiiii blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    31.     invoke_iiiii blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    32.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:8191020
    33.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:8053684
    34.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1638759
    35.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:1638549
    36.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3629433
    37.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3624549
    38.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:4840575
    39.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:4839832
    40.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:4013780
    41.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3685087
    42.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3685108
    43.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3681723
    44.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:3675176
    45.     <anonymous> blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8 line 8 > WebAssembly.instantiate:14516183
    46.     dynCall_v blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    47.     browserIterationFunc blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    48.     runIter blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    49.     Browser_mainLoop_runner blob:null/4252c009-27c1-44f6-b9df-3078cec7e1f8:8
    I just updated the local game Newtonsoft.dll to the lastest version. This appears to not even convert the object into json. So this appears to be inside Unity I think. I have so new debug code:

    Code (CSharp):
    1. using Newtonsoft.Json;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Data;
    6. using System.IO;
    7. using System.Net;
    8. using System.Net.Http;
    9. using System.Runtime.Serialization.Formatters.Binary;
    10. using System.Text;
    11. using UnityEngine;
    12. using UnityEngine.Networking;
    13. using UnityEngine.UI;
    14. using WBG_4;
    15.  
    16. public class send : MonoBehaviour
    17. {
    18.     public Text txtResponse;
    19.     public Text txtDebug;
    20.  
    21.     private string _Response;
    22.  
    23.     public void Send()
    24.     {
    25.         txtDebug.text = "Click button";
    26.         string uri = WBG_Config._EndPoint + "api/WhiteBoXGaming/Post_TestAPI";
    27.         OAuth oAuth = new OAuth();
    28.  
    29.         txtDebug.text = "define object";
    30.         oAuth.Administrator = WBG_Config._OAuth_Admin;
    31.         oAuth.Password = WBG_Config._OAuth_Password;
    32.  
    33.         txtDebug.text = "json";
    34.         string json = JsonConvert.SerializeObject(oAuth);
    35.  
    36.         txtDebug.text = "StartCoroutine";
    37.         StartCoroutine(GetJsonContent(uri, json));
    38.     }
    39.  
    40.     IEnumerator Post(string url, string bodyJsonString)
    41.     {
    42.         var request = new UnityWebRequest(url, "POST");
    43.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    44.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    45.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    46.         request.SetRequestHeader("Content-Type", "application/json");
    47.  
    48.         txtDebug.text = request.ToString();
    49.  
    50.         yield return request.Send();
    51.      
    52.         Debug.Log("Status Code: " + request.responseCode);
    53.  
    54.         var response = request.downloadHandler.data;
    55.         string json = System.Text.Encoding.UTF8.GetString(response);
    56.         var _Response = JsonConvert.DeserializeObject<string>(json);
    57.  
    58.         yield return _Response;
    59.  
    60.         txtResponse.text = _Response;
    61.     }
    62.  
    63.     IEnumerator GetJsonContent(string url, string bodyJsonString)
    64.     {
    65.         var request = UnityWebRequest.Post(url, "{}");
    66.         request.method = "POST";
    67.  
    68.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    69.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    70.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    71.         request.SetRequestHeader("Content-Type", "application/json");
    72.  
    73.         txtDebug.text = "Sent";
    74.         yield return request.SendWebRequest();
    75.         txtDebug.text = "Returned";
    76.         while (!request.isDone)
    77.         {
    78.             yield return new WaitForEndOfFrame();
    79.         }
    80.  
    81.         if (request.isNetworkError)
    82.         {
    83.             txtDebug.text = request.error;
    84.             Debug.Log(request.error);
    85.         }
    86.         else
    87.         {
    88.             //var jsonContent = request.downloadHandler.text;
    89.  
    90.             var response = request.downloadHandler.data;
    91.             string json = System.Text.Encoding.UTF8.GetString(response);
    92.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    93.  
    94.             txtResponse.text = _Response.Http_Response;
    95.         }
    96.  
    97.         yield break;
    98.     }
    99. }
    100.  
     
  37. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Breaks on line 33:

    https://whiteboxgaming.com/webgl/

    Look at debug text you can see because next line should be Start Coroutine. So it wants to break when it trys to conver object to Json string
     
  38. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    8,960
    Remove JSON from the equation, as mentioned. Simplify! Good luck on your project.
     
  39. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    4,866
    The error message means that Newtonsoft JSON is attempting to use dynamic code generation, which is not allowed with IL2CPP, so won't work with WebGL. You should be able to do JSON serialization, but make sure that the JSON library has an AOT mode.
     
    Bunny83 likes this.
  40. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    521
    That's why I always use my own SimpleJSON library for web communication. It's not an object mapper but a simple parser / generator which provides an easy interface to work with the json data. There's also an extension file for common Unity types which simplify reading writing vectors, colors and some other types.

    Personally I think strict object mapping is in general not a great approach for a json based web API as depending on the API you may receive different responses. Most APIs have a different structure when an error happened. Strongly typed languages are quite unflexible in this field. That's why my class uses strongly typed dictionary and array based classes which allow the usage without the need of manually casting the values.

    Though of course it depends on how you consume the data in the end.

    As great and versatile Json.Net is, especially for webGL builds the library is unnecessarily huge.
     
  41. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    So here is the ultimate issue issue I ran into. My website that I uploaded WebGL too is HTTPS and the API lives on HTTP. I got a error that you cant receive data from HTTP to HTTPS. So the POST was blocked after I fixed the Json issue above. Those of you who are having issues with the Json issue here is Unity solution: https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347 No idea if there is a updated version of Json for Unity but it appears to work with IL2CPP. I'm going to try uploading to a non HTTPS host and see if I can get it working. I think their are some free hosts I can use for testing.
     
  42. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Update:
    I uploaded to this site:whiteboxgaming.infinityfreeapp.com

    I'm getting this error from CORS
    Access to XMLHttpRequest at 'http://www.whiteboxgaming.xyz:34188/api/WhiteBoXGaming/Post_TestAPI' from origin 'http://whiteboxgaming.infinityfreeapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    Not sure what to make of this or how to fix this issue. Is this API side or Unity side?

    Update
    Just a shot in the dark I'm going to try adding this

    Code (CSharp):
    1. IEnumerator GetJsonContent(string url, string bodyJsonString)
    2.     {
    3.         var request = UnityWebRequest.Post(url, "{}");
    4.         request.method = "POST";
    5.  
    6.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    7.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    8.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    9.         request.SetRequestHeader("Content-Type", "application/json");
    10.         request.GetResponseHeader("Access-Control-Allow-Origin");
    11.  
    12.         txtDebug.text = "Sent";
    13.         yield return request.SendWebRequest();
    14.         txtDebug.text = "Returned";
    15.         while (!request.isDone)
    16.         {
    17.             yield return new WaitForEndOfFrame();
    18.         }
    19.  
    20.         if (request.isNetworkError)
    21.         {
    22.             txtDebug.text = request.error;
    23.             Debug.Log(request.error);
    24.         }
    25.         else
    26.         {
    27.             //var jsonContent = request.downloadHandler.text;
    28.  
    29.             var response = request.downloadHandler.data;
    30.             string json = System.Text.Encoding.UTF8.GetString(response);
    31.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    32.  
    33.             txtResponse.text = _Response.Http_Response;
    34.         }
    35.  
    36.         yield break;
    37.     }
     
    Last edited: Jan 15, 2021 at 3:25 PM
  43. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    I think I'm missing something, I'm getting this error:
    Access to XMLHttpRequest at 'http://www.whiteboxgaming.xyz:34188/api/WhiteBoXGaming/Post_TestAPI' from origin 'http://whiteboxgaming.infinityfreeapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    I've researched it and it says I need to add "Access-Control-Allow-Origin" Here is updated code:
    Code (CSharp):
    1. IEnumerator GetJsonContent(string url, string bodyJsonString)
    2.     {
    3.         var request = UnityWebRequest.Post(url, "{}");
    4.         request.method = "POST";
    5.  
    6.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    7.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    8.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    9.         request.SetRequestHeader("Access-Control-Allow-Origin", "*");
    10.         request.SetRequestHeader("Content-Type", "application/json");
    11.        
    12.  
    13.         txtDebug.text = "Sent";
    14.         yield return request.SendWebRequest();
    15.         txtDebug.text = "Returned";
    16.         while (!request.isDone)
    17.         {
    18.             yield return new WaitForEndOfFrame();
    19.         }
    20.  
    21.         if (request.isNetworkError)
    22.         {
    23.             txtDebug.text = request.error;
    24.             Debug.Log(request.error);
    25.         }
    26.         else
    27.         {
    28.             //var jsonContent = request.downloadHandler.text;
    29.  
    30.             var response = request.downloadHandler.data;
    31.             string json = System.Text.Encoding.UTF8.GetString(response);
    32.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    33.  
    34.             txtResponse.text = _Response.Http_Response;
    35.         }
    36.  
    37.         yield break;
    38.     }
     
  44. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    getting a new error:
    InvalidOperationException: Header name contains invalid characters
    at UnityEngine.Networking.UnityWebRequest.SetRequestHeader (System.String name, System.String value) [0x00000] in <00000000000000000000000000000000>:0


    code:
    Code (CSharp):
    1. IEnumerator GetJsonContent(string url, string bodyJsonString)
    2.     {
    3.         var request = UnityWebRequest.Post(url, "{}");
    4.         request.method = "POST";
    5.  
    6.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    7.         request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    8.         request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    9.         txtDebug.text = "Access-Control-Allow-Origin: *";
    10.         request.SetRequestHeader("Access-Control-Allow-Origin", "*");
    11.         txtDebug.text = "Access-Control-Allow-Origin: true";
    12.         request.SetRequestHeader("Access-Control-Allow-Credentials:", "true");
    13.         txtDebug.text = "Content type json";
    14.         request.SetRequestHeader("Content-Type", "application/json");
    15.        
    16.  
    17.         txtDebug.text = "Sent";
    18.         yield return request.SendWebRequest();
    19.         txtDebug.text = "Returned";
    20.         while (!request.isDone)
    21.         {
    22.             yield return new WaitForEndOfFrame();
    23.         }
    24.  
    25.         if (request.isNetworkError)
    26.         {
    27.             txtDebug.text = request.error;
    28.             Debug.Log(request.error);
    29.         }
    30.         else
    31.         {
    32.             //var jsonContent = request.downloadHandler.text;
    33.  
    34.             var response = request.downloadHandler.data;
    35.             string json = System.Text.Encoding.UTF8.GetString(response);
    36.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    37.  
    38.             txtResponse.text = _Response.Http_Response;
    39.         }
    40.  
    41.         yield break;
    42.     }
    Added some more debugging
     
  45. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Now im getting new error from Unity:

    base = "System.InvalidOperationException: Header name contains invalid characters\r\n at UnityEngine.Networking.UnityWebRequest.SetRequestHeader (System.String name, System.String value) [0x00053] in C:\\buildslave\\unity\\build\\Modules\\UnityWebRequest\\Public\...

    So I dont know how to resolve this:
    Code (CSharp):
    1. IEnumerator GetJsonContent(string url, string bodyJsonString)
    2.     {
    3.         string EndPoint = WBG_Config._EndPoint;
    4.         var request = UnityWebRequest.Post(url, "{}");
    5.         request.method = "POST";
    6.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    7.  
    8.         try
    9.         {
    10.             request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
    11.             request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    12.             txtDebug.text = "Access-Control-Allow-Origin: *";
    13.             request.SetRequestHeader("Access-Control-Allow-Origin", EndPoint);
    14.             txtDebug.text = "Access-Control-Allow-Origin: true";
    15.             request.SetRequestHeader("Access-Control-Allow-Credentials:", "true");
    16.             txtDebug.text = "Content type json";
    17.             request.SetRequestHeader("Content-Type", "application/json");
    18.         }
    19.         catch (Exception ex)
    20.         {
    21.             Debug.Log(ex.Message);
    22.         }      
    23.        
    24.         txtDebug.text = "Sent";
    25.         yield return request.SendWebRequest();
    26.         txtDebug.text = "Returned";
    27.         while (!request.isDone)
    28.         {
    29.             yield return new WaitForEndOfFrame();
    30.         }
    31.  
    32.         if (request.isNetworkError)
    33.         {
    34.             txtDebug.text = request.error;
    35.             Debug.Log(request.error);
    36.         }
    37.         else
    38.         {
    39.             //var jsonContent = request.downloadHandler.text;
    40.  
    41.             var response = request.downloadHandler.data;
    42.             string json = System.Text.Encoding.UTF8.GetString(response);
    43.             var _Response = JsonConvert.DeserializeObject<WBGString>(json);
    44.  
    45.             txtResponse.text = _Response.Http_Response;
    46.         }
    47.  
    48.         yield break;
    49.     }
     
  46. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,766
    Was about to recommend that one, it's definitely a working solution, at least for most of the cases.

    Your server needs to add the information to its response's header. The client cannot do that.
     
  47. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
    Here is API code. Not sure what you want me to add?

    Code (CSharp):
    1.         public WBGString WhiteBoxGaming_Test([FromBody]OAuth oAuth)
    2.         {          
    3.             bool AccessGranted = _DataHelper.OAuth(oAuth.Administrator, oAuth.Password);
    4.             WBGString WBGString = new WBGString();
    5.  
    6.             if (AccessGranted)
    7.             {
    8.                 WBGString.Http_Response = "White Box Gaming Established 2018 All Rights Reserved";
    9.             }
    10.             else
    11.             {
    12.                 WBGString.Http_Response = "Access Denied";
    13.             }
    14.  
    15.             return WBGString;
    16.         }
     
  48. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    325
  49. VolodymyrBS

    VolodymyrBS

    Joined:
    May 15, 2019
    Posts:
    40
unityunity