Search Unity

Script works with Mono outside Unity but not in Unity

Discussion in 'Scripting' started by goddatr, Mar 21, 2018.

  1. goddatr

    goddatr

    Joined:
    Mar 16, 2018
    Posts:
    26
    I have a C# script to connect to a rest API with HTTPS that works well in a Mono Console project.
    When I copy the code into a Unity C# script to use it inside my project that script don't have the expected behaviour : It infinitly stall at the beginning of the response callback. (It print "Response CB" and then does nothing else)
    I don't understand why it wouldn't work in Unity when it works fine with Mono. The only difference between the two codes is just that Unity's script extends from MonoBehaviour...


    Here is the code of the Mono Program :

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Net;
    5. using System.Net.Security;
    6. using System.Security.Cryptography.X509Certificates;
    7.  
    8. namespace ConsoleApp1
    9. {
    10.     class Program
    11.     {
    12.         static void Main(string[] args)
    13.         {
    14.             string BASE_URL = "endpoint-api-addr";
    15.             string params= "params";
    16.  
    17.             GetRequest(BASE_URL + params);
    18.             Console.ReadLine();
    19.         }
    20.  
    21.         static void GetRequest(string uri)
    22.         {
    23.             System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
    24.  
    25.             //Accept any certificate
    26.             ServicePointManager.ServerCertificateValidationCallback += (p1, p2, p3, p4) => true;
    27.             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    28.  
    29.             request.BeginGetResponse(ResponseCallback, request);
    30.  
    31.         }
    32.  
    33.         static private void ResponseCallback(IAsyncResult result)
    34.         {
    35.             Console.WriteLine("Response CB");
    36.             HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
    37.             Console.WriteLine("1");
    38.             Stream dataStream = response.GetResponseStream();
    39.             Console.WriteLine("2");
    40.             StreamReader reader = new StreamReader(dataStream);
    41.             Console.WriteLine("3");
    42.             string responseFromServer = reader.ReadToEnd();
    43.             Console.WriteLine("4");
    44.  
    45.             Console.WriteLine("responseFromServer=" + responseFromServer);
    46.         }
    47.  
    48.     }
    49. }
    And here is the Unity's C# script :

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.IO;
    5. using System.Net;
    6. using System.Net.Security;
    7. using System.Security.Cryptography.X509Certificates;
    8. using UnityEngine;
    9.  
    10. public class TestAPI : MonoBehaviour {
    11.  
    12.     // Use this for initialization
    13.     void Start () {
    14.         string BASE_URL = "api-endpoint-addr";
    15.         string params = "params";
    16.  
    17.         GetRequest(BASE_URL + params);
    18.     }
    19.  
    20.     void GetRequest(string uri)
    21.     {
    22.         System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
    23.  
    24.         //Accept any certificate (for dev)
    25.         ServicePointManager.ServerCertificateValidationCallback += (p1, p2, p3, p4) => true;
    26.         HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    27.  
    28.         request.BeginGetResponse(ResponseCallback, request);
    29.  
    30.     }
    31.  
    32.     static private void ResponseCallback(IAsyncResult result)
    33.     {
    34.         Debug.Log("Response CB");
    35.         HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
    36.         Debug.Log("1");
    37.         Stream dataStream = response.GetResponseStream();
    38.         Debug.Log("2");
    39.         StreamReader reader = new StreamReader(dataStream);
    40.         Debug.Log("3");
    41.         string responseFromServer = reader.ReadToEnd();
    42.         Debug.Log("4");
    43.  
    44.         Debug.Log("responseFromServer=" + responseFromServer);
    45.     }
    46. }
     
  2. goddatr

    goddatr

    Joined:
    Mar 16, 2018
    Posts:
    26
    Surrounding lines 35 to 44 by a try catch block in Unity revealed an hidden error :
    SecureChannelFailure (The authentication or decryption has failed)

    But I still don't get why it's different from Mono.
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
  4. goddatr

    goddatr

    Joined:
    Mar 16, 2018
    Posts:
    26
    I don't think they are different, I used the version of Mono packaged with Unity.

    I tried UnityWebRequest and Unity's WWW class but from the forums I believe they cannot handle self signed certificates. That's why I use C#'s HttpWebRequest.

    And maybe I'm wrong but Unity doesn't seems to use the ServicePointManager.ServerCertificateValidationCallback...
    I added a Debug.Log inside and nothing shows up in console
     
  5. goddatr

    goddatr

    Joined:
    Mar 16, 2018
    Posts:
    26
    Seems to be due to Unity's incomplete Mono support.

    I solved it be switching to Unity beta 2018.1 and going back to UnityWebRequest which got a CertificateHandler (in beta)