Newtonsoft.Json reference complaining on Azure Functions
Solution 1
@JustInChronicles, I'm adding this here as an answer for reference, but the expected behavior should be that indirect dependencies of private assemblies are resolved from your bin
folder, as expected.
I put together the following test to reproduce your scenario:
- Created a simple class library with a simple type that uses Json.NET to serialize an object and return the JSON string. This assembly references Json.NET 8.0.3. The result includes the Json.NET assembly version it is using
- Created a function that references that type only with a
#r "DependencyWithJsonRef.dll"
and returns the result produced by the method mentioned above - Deployed
DependencyWithJsonRef.dll
andNewtonsoft.Json.dll
(8.0.3) to my function'sbin
folder
Invoking the function produces the expected result.
Here is the function, for reference:
#r "DependencyWithJsonRef.dll"
using System.Net;
public static string Run(HttpRequestMessage req, TraceWriter log)
{
var myType = new DependencyWithJsonRef.TestType();
return myType.GetFromJson();
}
As you can see, no explicit reference to indirect dependencies (Json.NET) required.
This is the output I get:
{
"Prop1":"Test",
"Prop2":1,
"AssemblyName": "Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"
}
Quick note: One thing you may want to check, particularly if you've updated that dependency while developing your function is that assembly resultion results were not cached. A sure way to make sure you're starting with a clean slate is to (after you deploy your function and assemblies) go to Kudu and kill the non-scm w3wp process to see if that helps. I'd be curious to know if that does the trick as there are a few things we can to to improve this if it does.
Solution 2
Json.Net can be simply reference adding this line at the top of your Run.csx
file :
#r "Newtonsoft.Json"
See this article if you want to know which assemblies are automatically added by the Azure Functions hosting environment:
Otherwise, if you want to use a specific version of Json.Net, you should probably add a reference to Json.Net using nuget package:
So you need to add a Project.json file that look like this:
{
"frameworks": {
"net46":{
"dependencies": {
"Newtonsoft.Json": "8.0.3"
}
}
}
}
If your external dependency references Newtonsoft.Json
without using a nuget package, you can have a look at this post that explains how to upload your binaries:
Solution 3
After some trial-and-error approach. I found what the issue was here.
@FabioCavalcante gave me a hint using a file-based reference,
#r "Newtonsoft.Json.dll"
It didn't work actually. I've copied those four files to Azure Functions' bin
directory:
AzureFunctionsSample.Services.dll
AzureFunctionsSample.Services.pdb
Newtonsoft.Json.dll
Newtonsoft.Json.xml
It still gave me the same error, even though I did the file-based reference. Then, I found another file, AzureFunctionsSample.Services.dll.config
that actually defines assembly binding redirects like:
<?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>
After I copied this config file to the Azure Functions' bin
directory, it worked!
Lessons Learnt
- Use the file-based reference for
Newtonsoft.Json
,#r "Newtonsoft.Json.dll"
, if your external assembly also has a reference to it. - Make sure that the assembly binding redirect configuration exists in Azure Functions'
bin
directory.
Correct me, if I'm still wrong.
Cheers,
justinyoo
Cloud 🥑 @ Microsoft English: https://devkimchi.com Korean: https://blog.aliencube.org Personal: https://justinchronicles.net GitHub: https://github.com/aliencube
Updated on June 11, 2022Comments
-
justinyoo almost 2 years
I'm running an Azure Functions, called
SmsWebhook
. It calls a method in an external assembly,AzureFunctionsSample.Services.dll
that has a reference toNewtonsoft.Json 8.0.3
The details of my
Run.csx
looks like:#r "AzureFunctionsSample.Services.dll" using System.Net; using AzureFunctionsSample.Services public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { ... }
Within the
Run()
method above, I create an instance and call a method in the instance. However, whenever I call that method, I receive the following error: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).
I manually added the same version of
Newtonsoft.Json.dll
under thebin
directory, but still got the same error. Why is it complaining at theNewtonsoft.Json.dll
file?If I move all the logics within the external assembly into the
Run.csx
, it won't complain, by the way. -
justinyoo almost 8 yearsUnfortunately, this is not the case.I did add
#r "Newtonsoft.Json"
andusing Newtonsoft.Json;
in myrun.csx
file, even though these are not directly used in the file. I also addedproject.json
with the NuGet reference like you suggested, but this didn't help me. -
justinyoo almost 8 yearsMy issue is that the Json.NET library couldn't be loaded, even though it's there.
-
Thomas almost 8 yearsdo you have the exact exception that is thrown ?
-
Fabio Cavalcante almost 8 yearsThat is why I was asking about a file based reference (with the DLL extension) as that would trigger a private assembly load, as opposed to the shared assembly that doesn't match the version you expect. Can you give that a try?
-
Fabio Cavalcante almost 8 yearsAlso, if you continue to see the issue after making that chang, please try to restart your site under settings.
-
justinyoo almost 8 years@FabioCavalcante I did
#r "Newtonsoft.Json.dll"
and still doesn't work. However, it seems that I found what the issue here I have. -
Fabio Cavalcante almost 8 yearsDo you mind sharing? I just finished testing your original scenario (dependency with a reference to Json.net 8.0.3) and with both deployed to bin, it works as expected. The Functions runtime will attempt to resolve private assembly dependencies from the private location. Is it possible you were missing the right assembly version when you first tried?
-
justinyoo almost 8 years@FabioCavalcante I wrote another answer, instead of leaving here as a comment. Please have a look and correct me, if I missed anything.
-
Fabio Cavalcante almost 8 yearsI'm glad this is working for you! As mentioned in my previous comment, those steps shouldn't be required, though. Just having your direct dependency #r reference in the function and making sure the expected version of Json.NET is deployed into your bin folder should work as expected. Not sure if you want to go through those steps, but it would be interesting to have the setup described above, making sure you restart the host (to ensure a clean slate with assembly resolution) to see if that works. As mentioned, I reproduced your scenario and it worked as described here.
-
Fabio Cavalcante almost 8 yearsAnother small clarification; you do not need to add explicit references to indirect dependencies. So the
#r "Newtonsoft.Json.dll"
(or with simple name) shouldn't be required at all. -
justinyoo almost 8 yearsThanks! After I restart the function app itself (because basically it's a web app), I don't have to have a file reference,
#r "Newtonsoft.Json.dll"
, but#r "Newtonsoft.Json"
was enough, if I need to use it in therun.csx
file. If I don't need it, the reference was not necessary. -
justinyoo almost 8 yearsBut, if I don't put the
Newtonsoft.Json.dll
assembly into thebin
directory, it gets an error. I'm still curious, why I should have the assembly, even though it's already internally referenced. -
Fabio Cavalcante almost 8 yearsYou shouldn't need the file reference if you're referencing the shared assembly (simple name), if you need a specific version, though, you'd place the file in your bin folder and reference with the extension.
-
Cameron Taggart about 7 years@FabioCavalcante Do you know how to avoid
Could not load file or assembly 'log4net, Version=1.2.15.0
? Any place I can add the binding redirects?