Newtonsoft.Json 参考抱怨 Azure Functions
Newtonsoft.Json reference complaining on Azure Functions
我是 运行 一个 Azure Functions,叫做 SmsWebhook
。它调用外部程序集 AzureFunctionsSample.Services.dll
中的方法,该方法引用了 Newtonsoft.Json 8.0.3
我的 Run.csx
的详细信息如下:
#r "AzureFunctionsSample.Services.dll"
using System.Net;
using AzureFunctionsSample.Services
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
...
}
在上面的 Run()
方法中,我创建了一个实例并在该实例中调用了一个方法。但是,每当我调用该方法时,都会收到以下错误:
2016-05-19T13:41:45 Welcome, you are now connected to log-streaming service.
2016-05-19T13:41:46.878 Function started (Id=64fccf0c-d0ef-45ef-ac1c-7736adc94566)
2016-05-19T13:41:46.878 C# HTTP trigger function processed a request. RequestUri=https://ase-dev-fn-demo.azurewebsites.net/api/smswebhook
2016-05-19T13:41:46.878 Function completed (Failure, Id=64fccf0c-d0ef-45ef-ac1c-7736adc94566)
2016-05-19T13:41:46.894 Exception while executing function: Functions.SmsWebhook. Microsoft.Azure.WebJobs.Script: One or more errors occurred. AzureFunctionsSample.Services: Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040).
我在bin
目录下手动添加了相同版本的Newtonsoft.Json.dll
,还是出现同样的错误。为什么它在 Newtonsoft.Json.dll
文件中抱怨?
如果我将外部程序集中的所有逻辑移动到 Run.csx
,顺便说一句,它不会抱怨。
Json.Net 可以简单地参考在 Run.csx
文件的顶部添加这一行:
#r "Newtonsoft.Json"
如果您想了解 Azure Functions 托管环境自动添加了哪些程序集,请参阅本文:
否则,如果您想使用特定版本的 Json.Net,您可能应该使用 nuget 包添加对 Json.Net 的引用:
因此您需要添加一个 Project.json 文件,如下所示:
{
"frameworks": {
"net46":{
"dependencies": {
"Newtonsoft.Json": "8.0.3"
}
}
}
}
如果您的外部依赖项引用 Newtonsoft.Json
而不使用 nuget 包,您可以查看这个 post,它解释了如何上传您的二进制文件:
经过反复试验。我发现问题出在这里。
@FabioCavalcante 使用基于文件的参考给了我一个提示,
#r "Newtonsoft.Json.dll"
实际上没有用。我已将这四个文件复制到 Azure Functions 的 bin
目录:
AzureFunctionsSample.Services.dll
AzureFunctionsSample.Services.pdb
Newtonsoft.Json.dll
Newtonsoft.Json.xml
它仍然给了我同样的错误,即使我做了基于文件的引用。然后,我找到了另一个文件 AzureFunctionsSample.Services.dll.config
,它实际上定义了程序集绑定重定向,例如:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
将此配置文件复制到 Azure Functions 的 bin
目录后,它成功了!
经验教训
- 如果您的外部程序集也有对它的引用,请使用
Newtonsoft.Json
、#r "Newtonsoft.Json.dll"
的基于文件的引用。
- 确保程序集绑定重定向配置存在于 Azure Functions 的
bin
目录中。
如果我仍然错了,请纠正我。
干杯,
@JustInChronicles,我在这里添加这个作为参考的答案,但预期的行为应该是私有程序集的间接依赖性按照预期从您的 bin
文件夹中解析。
我整理了以下测试来重现您的场景:
- 创建了一个简单的 class 库,其类型简单,使用 Json.NET 序列化对象和 return JSON 字符串。此程序集引用 Json.NET 8.0.3。结果包括它正在使用的Json.NET 程序集版本
- 创建了一个函数,该函数仅引用 类型
#r "DependencyWithJsonRef.dll"
并且 return 是上述方法产生的结果
- 已将
DependencyWithJsonRef.dll
和 Newtonsoft.Json.dll
(8.0.3) 部署到我函数的 bin
文件夹
调用该函数会产生预期的结果。
这里是函数,供参考:
#r "DependencyWithJsonRef.dll"
using System.Net;
public static string Run(HttpRequestMessage req, TraceWriter log)
{
var myType = new DependencyWithJsonRef.TestType();
return myType.GetFromJson();
}
如您所见,不需要显式引用间接依赖项 (Json.NET)。
这是我得到的输出:
{
"Prop1":"Test",
"Prop2":1,
"AssemblyName": "Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"
}
快速说明:您可能需要检查一件事,特别是如果您在开发函数时更新了该依赖项,那就是未缓存程序集结果。确保从头开始的可靠方法是(在部署函数和程序集之后)转到 Kudu 并终止 non-scm w3wp 进程以查看是否帮助。我很想知道这是否有效,因为如果有效,我们可以做一些改进。
我是 运行 一个 Azure Functions,叫做 SmsWebhook
。它调用外部程序集 AzureFunctionsSample.Services.dll
中的方法,该方法引用了 Newtonsoft.Json 8.0.3
我的 Run.csx
的详细信息如下:
#r "AzureFunctionsSample.Services.dll"
using System.Net;
using AzureFunctionsSample.Services
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
...
}
在上面的 Run()
方法中,我创建了一个实例并在该实例中调用了一个方法。但是,每当我调用该方法时,都会收到以下错误:
2016-05-19T13:41:45 Welcome, you are now connected to log-streaming service.
2016-05-19T13:41:46.878 Function started (Id=64fccf0c-d0ef-45ef-ac1c-7736adc94566)
2016-05-19T13:41:46.878 C# HTTP trigger function processed a request. RequestUri=https://ase-dev-fn-demo.azurewebsites.net/api/smswebhook
2016-05-19T13:41:46.878 Function completed (Failure, Id=64fccf0c-d0ef-45ef-ac1c-7736adc94566)
2016-05-19T13:41:46.894 Exception while executing function: Functions.SmsWebhook. Microsoft.Azure.WebJobs.Script: One or more errors occurred. AzureFunctionsSample.Services: Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040).
我在bin
目录下手动添加了相同版本的Newtonsoft.Json.dll
,还是出现同样的错误。为什么它在 Newtonsoft.Json.dll
文件中抱怨?
如果我将外部程序集中的所有逻辑移动到 Run.csx
,顺便说一句,它不会抱怨。
Json.Net 可以简单地参考在 Run.csx
文件的顶部添加这一行:
#r "Newtonsoft.Json"
如果您想了解 Azure Functions 托管环境自动添加了哪些程序集,请参阅本文:
否则,如果您想使用特定版本的 Json.Net,您可能应该使用 nuget 包添加对 Json.Net 的引用:
因此您需要添加一个 Project.json 文件,如下所示:
{
"frameworks": {
"net46":{
"dependencies": {
"Newtonsoft.Json": "8.0.3"
}
}
}
}
如果您的外部依赖项引用 Newtonsoft.Json
而不使用 nuget 包,您可以查看这个 post,它解释了如何上传您的二进制文件:
经过反复试验。我发现问题出在这里。
@FabioCavalcante 使用基于文件的参考给了我一个提示,
#r "Newtonsoft.Json.dll"
实际上没有用。我已将这四个文件复制到 Azure Functions 的 bin
目录:
AzureFunctionsSample.Services.dll
AzureFunctionsSample.Services.pdb
Newtonsoft.Json.dll
Newtonsoft.Json.xml
它仍然给了我同样的错误,即使我做了基于文件的引用。然后,我找到了另一个文件 AzureFunctionsSample.Services.dll.config
,它实际上定义了程序集绑定重定向,例如:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
将此配置文件复制到 Azure Functions 的 bin
目录后,它成功了!
经验教训
- 如果您的外部程序集也有对它的引用,请使用
Newtonsoft.Json
、#r "Newtonsoft.Json.dll"
的基于文件的引用。 - 确保程序集绑定重定向配置存在于 Azure Functions 的
bin
目录中。
如果我仍然错了,请纠正我。
干杯,
@JustInChronicles,我在这里添加这个作为参考的答案,但预期的行为应该是私有程序集的间接依赖性按照预期从您的 bin
文件夹中解析。
我整理了以下测试来重现您的场景:
- 创建了一个简单的 class 库,其类型简单,使用 Json.NET 序列化对象和 return JSON 字符串。此程序集引用 Json.NET 8.0.3。结果包括它正在使用的Json.NET 程序集版本
- 创建了一个函数,该函数仅引用 类型
#r "DependencyWithJsonRef.dll"
并且 return 是上述方法产生的结果 - 已将
DependencyWithJsonRef.dll
和Newtonsoft.Json.dll
(8.0.3) 部署到我函数的bin
文件夹
调用该函数会产生预期的结果。
这里是函数,供参考:
#r "DependencyWithJsonRef.dll"
using System.Net;
public static string Run(HttpRequestMessage req, TraceWriter log)
{
var myType = new DependencyWithJsonRef.TestType();
return myType.GetFromJson();
}
如您所见,不需要显式引用间接依赖项 (Json.NET)。
这是我得到的输出:
{
"Prop1":"Test",
"Prop2":1,
"AssemblyName": "Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"
}
快速说明:您可能需要检查一件事,特别是如果您在开发函数时更新了该依赖项,那就是未缓存程序集结果。确保从头开始的可靠方法是(在部署函数和程序集之后)转到 Kudu 并终止 non-scm w3wp 进程以查看是否帮助。我很想知道这是否有效,因为如果有效,我们可以做一些改进。