Problems with Newtonsoft.Json.Rhino

I have the code from my plugin segregated into two major parts, the base is built without references to any Rhino assemblies. In this way I can reuse these parts in other contexts. I use the Newtonsoft.Json library for serialization in this code.

The Rhino plugin portion of the code references these projects as well as RhinoCommon. When I upgraded the the referenced RhinoCommon from 7.1 to 7.6 things broke. This comes down to RhinoCommon now shipping with Newtonsoft.Json.Rhino - a vendorized version of Newtonsoft.Json. The namespaces arenā€™t changed in this vendorized version, so there is a conflict if my code references Newtonsoft.Json. It finds the same object in the version Iā€™m referencing and the version provided by RhinoCommon.

Other than reverting back to RhinoCommon 7.1, itā€™s not obvious to me how to fix this. I think Iā€™m an edge case, but the short of it is, that this prevents me from using Newtonsoft as I have been doing for several years.

For context, this plugin has been alive since 2005. I use shared projects in Visual Studio to aid me in building the plugins against Rhino 5, 6, and 7.

1 Like

As I see it, you have three options:

  1. Revert back to an earlier RhinoCommon nuget package
  2. Add new build flavors (Debug-Rhino7, Release-Rhino7) to your shared project that references Newtonsoft.Json.Rhino instead of Newtonsoft.Json
  3. Use extern alias to reference Newtonsoft.Json in your plug-in code (extern alias - C# Reference | Microsoft Docs)

I would recommend option (2). This lets you ship without a copy of Newtonsoft.Json for Rhino 7. We built a vendorized version of the DLL as we were getting version mismatch conflicts due to the fact that so many people use Newtonsoft.Json and there are so many versions out there. For option (2) it usually required some manual editing of the csproj file, but we can help here if you choose to go that route.

This created a horrible mess in our 40+ project solution. Had to manually edit 42 project files, to put the alias on the NuGet package, and then modify 157 files with the extern reference in order to unravel thisā€¦

Couldnā€™t you have modified the Namespaces in Newtonsoft.Json.Rhino so your custom Newtonsoft assembly wouldnā€™t collide with everyone using the official package from Newtonsoft?

For now Iā€™ve chosen to stick with a version that doesnā€™t bundle NewtonSoft. I will likely need to revisit this later. Particularly if the sdk gets really interesting for me for SubDs.

Yeah it was quite a nightmareā€¦ 3000+ errors in our solution that I had to go to each file and fix the referencesā€¦ Not fun.

If you decide to tackle it, this is what I had to do:

And then

1 Like

Is there a reason you need the official Newtonsoft.json? We shipped the Rhino version because we were getting so many conflicts from different plugins shipping different versions of this library

1 Like

We have 43 projects across three applications built upon a common core set of libraries.

Json is used in most of our applications, however Rhino is not. I would never expect to find a public NuGet package inside another vendors software.

We like NuGet because it allows each piece of software to go get the version it needs. Conflicts can be solved with binding redirects.

I think conflicts could have been avoided having just reference the official package and then put the binding redirects in the app.config file for Rhino.

But this extern reference will work for now, it just caused me 3 hours of unplanned work unfortunately.

1 Like

For me, I have a portion of the code base used outside of Rhino. I have also been supporting Rhino 5 and 6. Though I believe most of my users have switched over to 7 at this point, Iā€™ve had some Rhino 5 users until very recently and may still have some stragglers. Iā€™ve got a bit of gymnastics to make that work with a single code base.

This plugin, while it has become essential to some of our work, is not what what Iā€™m mainly paid to do. So big (unanticipated) changes to project files to keep things compiling like they used to are quite a diversion.

1 Like

It wasnā€™t our intention to make things painful.

@will letā€™s pull this DLL out of our nuget package.

2 Likes

Done. The 7.8.* release of the RhinoCommon NuGet package wonā€™t include this assembly.

3 Likes

Thanks, Steve and Will. I am curious how issues on the other side of this manifested (the version conflicts you mentioned).

I certainly appreciate you werenā€™t trying to make this painful, Steve, and seriously appreciate all of the work you guys do on Rhino and the SDKs.

Thanks @stevebaer @will Iā€™ll stage my changes for now, and wait for 7.8.

1 Like

Different plugins would install different versions of Newtonsoft.json and conflicts which cause different things to fail would occur. This is such a popular assembly that it was happening quite a bit and even intefering with the version that Rhino itself ships. This is why we compiled our own version with a different name as ā€˜DLL hellā€™ still happens even in .NET.

Do you guys know which version you added the reference to Newtonsoft.json.rhino?

Or do you plan to release the NuGet for 2.8 soon?

Iā€™m going to need to rollback, because I cannot get our Azure Build Pipeline to work with the Extern Reference that worked locallyā€¦

I. believe we added the Newtonsoft.json assembly to our RhinoCommon nuget package in Rhino 7.7. Rhino 7.8 is scheduled to be released July 13th as we are trying to schedule service releases for the second Tuesday of every month.

1 Like

Actually, it was in v7.4.21067.13001 that Newtonsoft.Json.Rhino.dll was first included in the RhinoCommon package. v7.3.21053.23031 is the newest one without the additional assembly.

2 Likes

Where we can find Newtonsoft.Json.Rhino.dll now?

The DLL is not available on nuget with our latest RhinoCommon package. It exists in the Rhino system directory for your installed Rhino

1 Like

In case someone else runs into this, probably not the best way, but this is how Iā€™m dealing with this issue:

  • Iā€™m authoring a library that is used both within Rhino and outside, what I do is to target 2 frameworks ā€œnet framework 4.8ā€ and ā€œnet standard 2.0ā€.
  • Net framework is used only within Rhino and net standard everywhere else.
  • Net framework references NewtonSoft.Json.Rhino in the Rhino system folder with the flag to not copy it to the build folder, and Net standard references the nuget package.

These are the relevant parts of the .csproj file:

	<PropertyGroup>
		<TargetFrameworks>netstandard2.0;net48</TargetFrameworks>
	</PropertyGroup>

	<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
		<PackageReference Include="Rhino3dm" Version="7.11.0" />
		<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
	</ItemGroup>

	<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
		<PackageReference Include="RhinoCommon" Version="7.14.22010.17001" />
		<Reference Include="Newtonsoft.Json.Rhino">
			<HintPath>C:\Program Files\Rhino 7\System\Newtonsoft.Json.Rhino.dll</HintPath>
			<Private>False</Private>
		</Reference>
	</ItemGroup>

Oops, forgot that for a cloud build the Newtonsoft.Json.Rhino.dll has to be accessible to the server. I copied it to the repo and changed the file path accordingly for now.

I think it wasnā€™t a bad idea to include it in the Rhinocommon nuget package.