HttpClientExtensions.SetBearerToken 使用时预编译的 Azure 函数抛出错误,CSX 不会

Precompiled Azure Function throwing error on HttpClientExtensions.SetBearerToken use, CSX doesn't

所以首先,我使用以下博客 post 帮助我将我的 CSX Azure 函数转换为预编译的 class 库 - https://blogs.msdn.microsoft.com/appserviceteam/2017/03/16/publishing-a-net-class-library-as-a-function-app/?utm_source=Direct

我已经达到了我认为它应该工作的地步,但作为一个预编译函数,它在 SetBearerToken(在 System.Net.Http.HttpClientExtensions 中)上抛出一个 'Method Not Found' 异常,但它没有在 CSX 版本中找到此方法有任何问题。这是完整的错误:

Exception while executing function: Functions.notifications-queue-trigger Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: Functions.notifications-queue-trigger ---> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. ---> System.MissingMethodException : Method not found: 'Void System.Net.Http.HttpClientExtensions.SetBearerToken(System.Net.Http.HttpClient, System.String)'.

预编译函数和 CSX 脚本之间的代码几乎完全相同(明显需要的差异除外)。

我在这里错过了什么?为什么在预编译版本中 System.Net.Http.HttpClientExtensions 中的 SetBearerToken 抛出 'Method Not Found' 异常,而在编写为 CSX 脚本时没有问题?任何帮助表示赞赏。

这是我的 CSX 脚本函数,有效:

#r "IdentityModel.dll"
#r "Sorbet.DataTransferObjects.dll"
#r "Newtonsoft.Json"

using System;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;

using IdentityModel.Client;
using Newtonsoft.Json;
using Sorbet.DataTransferObjects;

public static void Run(NotificationDto myQueueItem, TraceWriter log)
{
    log.Info($"C# ServiceBus queue trigger function processed message");
    TokenResponse idToken;
    using (var tokenClient = new TokenClient("https://myidserver", "myclientid", "myclientsecret"))
    {
        var response = tokenClient.RequestClientCredentialsAsync("myscope");
        idToken = response.Result;
        log.Info($"Access token retrieved : {idToken.AccessToken}");
    }

    using (var apiClient = new HttpClient())
    {
        var apiUrl = "https://myapiurl/";
        var endpoint = "myendpoint";
        string data = JsonConvert.SerializeObject(myQueueItem);
        log.Info($"Hitting API...");

        apiClient.SetBearerToken(idToken.AccessToken);
        var response = apiClient.PostAsync($"{apiUrl}{endpoint}", new StringContent(data, Encoding.UTF8, "application/json")).Result;
    }
}

这是我的 C# 函数 class,这会在 SetBearerToken 调用中引发上述错误:

using System;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;

using IdentityModel.Client;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using Sorbet.DataTransferObjects;

namespace FunctionsClassLibTest
{
    public class NotificationQueueTrigger
    {
        public static void Run(NotificationDto myQueueItem, TraceWriter log)
        {
            log.Info($"C# ServiceBus queue trigger function processed message");
            TokenResponse idToken;
            using (var tokenClient = new TokenClient("https://myidserver", "myclientid", "myclientsecret"))
            {
                var response = tokenClient.RequestClientCredentialsAsync("myscope");
                idToken = response.Result;
                log.Info($"Access token retrieved : {idToken.AccessToken}");
            }

            using (var apiClient = new HttpClient())
            {
                var apiUrl = "https://myapiurl";
                var endpoint = "myendpoint";
                string data = JsonConvert.SerializeObject(myQueueItem);
                log.Info($"Hitting API...");

                apiClient.SetBearerToken(idToken.AccessToken);
                var response = apiClient.PostAsync($"{apiUrl}{endpoint}", new StringContent(data, Encoding.UTF8, "application/json")).Result;
            }
        }
    }
}

这是我的预编译函数的 function.json 文件(CSX 几乎相同,但只有绑定部分)

{
  "scriptFile": "..\bin\FunctionsClassLibTest.dll",
  "entryPoint": "FunctionsClassLibTest.NotificationQueueTrigger.Run",
  "bindings": [
    {
      "name": "myQueueItem",
      "type": "serviceBusTrigger",
      "direction": "in",
      "queueName": "notifications",
      "connection": "dev-bus",
      "accessRights": "manage"
    }
  ],
  "disabled": false
}

好的,所以我已经找到了解决方案。问题出在我认为一开始可能是正确的地方,在 IdentityModel 库中。我被抛出错误的名称空间抛出,这让我疯狂地追逐了几个小时。事实上,HttpClient 的扩展是在 IdentityModel 库中定义的。

确切地知道问题实际出在哪里,我查看了扩展并将 apiClient.SetBearerToken("myBearerToken"); 行替换为该扩展方法 apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "myBearerToken"); 中使用的代码,这现在可以在我的预编译中使用功能。

这并没有回答 为什么 它在 CSX 中工作而不是在预编译函数中工作的问题。如果有人对为什么会这样有任何想法,我真的很想知道!我知道导入 IdentityModel 库不是问题,因为我使用它从我的 ID 服务器获取令牌并且工作正常,所以它必须是特定于扩展方法的东西。有问题的扩展方法可以在这里看到 - https://github.com/IdentityModel/IdentityModel/blob/master/source/IdentityModel.Shared/Client/HttpClientExtensions.cs