'HoloLens 2 throwing NotSupportedException on System.Net.Http.WebRequestHandler

I am trying to use Azure Cognitive Services (OCR) on the HoloLens 2. I'm using their .NET demo application with Nuget for Unity and importing all the necessary libraries. Everything compiles the way it should, but in runtime on the HoloLens, the code fails to execute the authentication part, saying there's a NotSupportedException. I've checked Internet/Client capabilities in Unity and I'm using the .NET 2.0 API (using the .NET 4.x doesn't help either). The scripting backend is IL2CPP because it's a UWP app. I'm using Unity 2020.3.13. I've gone through Azure's services and double-checked my endpoints and keys and those all work fine. It works through the Unity editor but fails on the HoloLens side. I've tried adding in a 'using' statement for System.Net.Http and double-checked the .dll is included in my editor folder, but I'm not sure how to make the HoloLens support this call. How do I get the device to access the API from within the code? I am new to networking and POST/GET calls.

Here's the part from UnityPlayer.log that details the exception:

NotSupportedException: System.Net.Http.WebRequestHandler::.ctor
  at System.Net.Http.WebRequestHandler..ctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Microsoft.Rest.ServiceClient`1[T].CreateRootHandler () [0x00000] in <00000000000000000000000000000000>:0 
  at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <00000000000000000000000000000000>:0 
  at Microsoft.Azure.CognitiveServices.Vision.ComputerVision.ComputerVisionClient..ctor (Microsoft.Rest.ServiceClientCredentials credentials, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <00000000000000000000000000000000>:0 
  at MainController.Start () [0x00000] in <00000000000000000000000000000000>:0 

Here's my main program (I've shortened the unnecessary + working methods):

using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.WebCam;
using System.Net.Http;

using TMPro;

public class MainController : MonoBehaviour
{
    PhotoCapture photoCaptureObject = null;
    
    public TextMeshPro debugText;


    private ComputerVisionClient client;

    private static string subscriptionKey = "<key>";
    private static string endpoint = "<endpoint>";
    private string photoFilePath;


    // Start is called before the first frame update
    void Start()
    {
        debugText.text = "In start" + "\n";

        ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
        // fails here, in the HL, doesn't even go into the if block

        if (client == null)
        {
            debugText.text += "client is null" + "\n";
        }
        else
        {
            debugText.text += "client is not null" + "\n";
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public static ComputerVisionClient Authenticate(string endpoint, string key)
    {
        ComputerVisionClient client =
            new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
            { Endpoint = endpoint };
        return client;
    }

    public void CaptureImage()
    {
        // called from ImageCapture button in app
        PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
    }

    void OnPhotoCaptureCreated(PhotoCapture captureObject)
    {
         ...
        // code for use in the HL to capture an image from what the user is seeing
    }

    void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
    {
         ...
        // save photo as .jpg and store on device
    }

    void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
    {
         ...
        // check success result and stop photo mode
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.Dispose();
        photoCaptureObject = null;

        ReadFileLocal(client, photoFilePath).Wait();
    }

    public async Task ReadFileLocal(ComputerVisionClient client, string localFile)
    {
        debugText.text += "reading file from local" + "\n";
        string operationLocation = "";
        string operationId = "";

        if (!File.Exists(localFile))
        {
            debugText.text += "file does not exist in the path" + "\n";
        }
        else 
        {
            debugText.text += "file exists, continuing" + "\n";
        }


        try 
        {
            // Read text from URL
            var textHeaders = await client.ReadInStreamAsync(File.OpenRead(localFile));
            // After the request, get the operation location (operation ID)
            operationLocation = textHeaders.OperationLocation;
            Thread.Sleep(2000);
        }
        catch (Exception e)
        {
            debugText.text += "reading file failed" + "\n";
            debugText.text += "Exception: " + e + "\n";
        }
        

        // <snippet_extract_response>
        // Retrieve the URI where the recognized text will be stored from the Operation-Location header.
        // We only need the ID and not the full URL
        const int numberOfCharsInOperationId = 36;
        operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
        

        // Extract the text
        ReadOperationResult results;
        do
        {
            results = await client.GetReadResultAsync(System.Guid.Parse(operationId));
        }
        while ((results.Status == OperationStatusCodes.Running ||
            results.Status == OperationStatusCodes.NotStarted));
        // </snippet_extract_response>

        // <snippet_extract_display>
        // Display the found text.
        var textUrlFileResults = results.AnalyzeResult.ReadResults;
        foreach (ReadResult page in textUrlFileResults)
        {
            foreach (Line line in page.Lines)
            {
                debugText.text += line + "\n";
            }
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source