预编译的Azure函数抛出HttpClientExtensions.SetBearerToken时出错,CSX没有

时间:2017-04-12 10:34:02

标签: c# azure identityserver3 azure-functions

首先,我正在使用以下博文来帮助我将CSX Azure功能转换为预编译的类库 - 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脚本(显然不是所需的差异)。

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

这是我作为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#类的函数,这会在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
}

1 个答案:

答案 0 :(得分:1)

好的,所以我已经找到了解决方法。问题是我认为在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