Search Unity

Using WebClient to DownloadString() no longer works in Standalone build in 2021.x

Discussion in 'Scripting' started by Strom_CL, Jan 31, 2022.

  1. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    I have a very weird issue right now going on in 2021, previously all of this worked in 2019.x, we moved to 2021 a few weeks ago and I'm just now noticing this behavior. I am able to see my ExternalIP() function work when I run it in the Editor, but when I run it in a standalone build I'm getting nothing. I was able to run a standalone build with VS attached and I see this under my WebException, but nothing useful that I can see. This works 100% of the time in the Editor, and fails 100% of the time in standalone builds. I have also tried running this as Admin and I see the same issue. I know that 2021 is using C# 9.0 so I'm assuming something broke or was changed in how this worked previously back on 2019.

    Anyone have any ideas?

    Code (csharp):
    1.  
    2. "System.Net.WebException: An exception occurred during a WebClient request. ---> System.NullReferenceException: Object reference not set to an instance of an object\r\n  at System.Net.WebRequestPrefixElement..ctor (System.String P, System.Type creatorType) ...
    3.  
    Code (csharp):
    1.  
    2.     public static string ExternalIP()
    3.     {
    4.         System.Net.WebRequest.DefaultWebProxy = null;
    5.         string tmpExternalIP = "Error";
    6.         System.Net.WebClient tmpClient = new System.Net.WebClient();
    7.         tmpClient.Proxy = null;
    8.  
    9.         try
    10.         {
    11.             tmpExternalIP = tmpClient.DownloadString("http://ipinfo.io/ip");
    12.         }
    13.         catch (System.Net.WebException wex)
    14.         {
    15.             switch (wex.Status)
    16.             {
    17.                 case System.Net.WebExceptionStatus.ConnectFailure:
    18.                 case System.Net.WebExceptionStatus.NameResolutionFailure:
    19.                 case System.Net.WebExceptionStatus.Timeout:
    20.                 case System.Net.WebExceptionStatus.ProtocolError:
    21.                     tmpExternalIP = tmpClient.DownloadString("http://www.chargingllama.com/externalip.php");
    22.                     break;
    23.                 default:
    24.                     break;
    25.             }
    26.             Debug.Log("WebException Status: " + wex.Status.ToString());
    27.         }
    28.         return tmpExternalIP;
    29.     }
    30.  
     
    Last edited: Jan 31, 2022
  2. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    Found the issue.

    In my project settings, under Optimization I had the "Managed Stripping Level" set to "Low". This broke the WebClient call and was causing the null reference. I tried minimal and had the same results, so it looks like for whatever reason in 2021 if you have any managed stripping level set it will break a System.Net.WebClient call.

    Also marking my class: [UnityEngine.Scripting.Preserve] did not affect the function, it still fails with any level of Managed Stripping enabled.

    Problem: WebClient gets a null reference for no reason
    Solution: Disable managed stripping levels completely
     
    Last edited: Jan 31, 2022
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,999
    The issue most likely is not in your own code but in the internal code of the WebClient. The WebClient class may use reflection internally to actually create some internal classes. When Unity applies its stripping rules it may not find any direct usages of some of those internal classes and stripped them out. This is generally an issue with any dynamic code generation or reflection usage.

    Such issues usually do have solutions, but they are individual for the specific case / class. So you may need to dig deeper what classes are involved inside the WebClient and make sure all of them are preserved. In a lot cases it's enough to just ship a method which you never call that simply creates an instance of those classes / types. Sometimes that's not possible because the classes are internal / private.

    It seems others have gone through this before you.
     
  4. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    115
    Nice find, I didn't see that come up when I tried searching. Definitely prefer to have striping and apply more specific linker preservation like that post references. Thanks!