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
所以首先,我使用以下博客 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