March 20th, 2019

Using Newtonsoft.Json in a Visual Studio extension

Mads Kristensen
Principal Product Manager

The ever popular Newtonsoft.Json NuGet package by James Newton-King is used throughout Visual Studio’s code base. Visual Studio 2015 (14.0) was the first version to ship with it. Later updates to Visual Studio also updated its Newtonsoft.Json version when an internal feature needed it. Today it is an integral part of Visual Studio and you can consider it a part of the SDK alongside other Visual Studio assemblies.

Extensions can therefore also use the very same Newtonsoft.Json shipped with Visual Studio. It can, however, be confusing to know what version to reference and whether to ship the Newtonsoft.Json.dll file itself with the extension or not. And what if the extension supports older version of Visual Studio that doesn’t come with Newtonsoft.Json?

I promise it’s not confusing once you know how, so let’s start at the beginning with versioning.

Versioning

Just like any other Visual Studio SDK assemblies, extensions must reference lowest version matching the lower bound of supported Visual Studio versions. For instance, if the extension supports Visual Studio 14.0, 15.0, and 16.0, then it must reference the 14.0 SDK assemblies. The same is true for referencing Newtonsoft.Json, but it is less obvious to know what version shipped when.

Here’s the breakdown:

  • Visual Studio 17.0 – Newtonsoft.Json 13.0.1
  • Visual Studio 16.2 – Newtonsoft.Json 12.0.2
  • Visual Studio 16.0 – Newtonsoft.Json 9.0.1
  • Visual Studio 15.3 – Newtonsoft.Json 9.0.1
  • Visual Studio 15.0 – Newtonsoft.Json 8.0.3
  • Visual Studio 14.0 – Newtonsoft.Json 6.0.x
  • Visual Studio 12.0 – none

So, if your extension’s lowest supported Visual Studio version is 14.0, then you must reference Newtonsoft.Json version 6.0.x. In fact, make sure the entire dependency tree of your references doesn’t exceed that version.

Learn more about Visual Studio versioning in the blog post Visual Studio extensions and version ranges demystified.

Binding redirects

When referencing a lower version of Newtonsoft.Json than ships in Visual Studio, a binding redirect is in place to automatically change the reference to the later version at runtime. Here’s what that looks like in the devenv.exe.config file of Visual Studio 15.0:

<dependentAssembly>
  <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
  <bindingRedirect oldVersion="4.5.0.0-8.0.0.0" newVersion="8.0.0.0"/>
</dependentAssembly>

It makes sure that when an assembly references a version of Newtonsoft.Json that is older than 8.0.0.0, it automatically redirects to use the 8.0.0.0 version that ships in Visual Studio 15.0.

This is the same mechanism that makes it possible to use an SDK assembly such as Microsoft.VisualStudio.Language.Intellisense version 12.0 in Visual Studio 16.0. A binding redirect automatically changes the reference to the 16.0 version of that assembly.

Don’t ship it unless you need to

The rule of thumb is to not ship the Newtonsoft.Json.dll file in the .vsix container. Since Visual Studio always have a copy and does binding redirects, there is no reason to ship it.

However, there are two scenarios where you do want to ship the .dll with the extension.

  1. If your extension supports Visual Studio 12.0 or older
  2. If you absolutely need a newer version than shipped by Visual Studio

When supporting Visual Studio 12.0 or older, try to use Newtonsoft.Json version 6.0.x if possible. That ensures that when the extension runs in Visual Studio 14.0 and newer, then the .NET Framework won’t load the assembly from your extension, but instead use the one it ships with. That means fewer assemblies needed loading by the CLR.

If you ship your own version, then don’t expect to be able to exchange Newtonsoft.Json types with other assemblies in Visual Studio because they were compiled against a different version. Normally binding redirects unifies the versions, but not when shipping your own. Also specify a code base for it so Visual Studio can resolve it at runtime. You don’t always need to, but it’s considered best practice and avoids any issues. Simply add this line to your AssemblyInfo.cs file:

[assembly: ProvideCodeBase(AssemblyName = "Newtonsoft.Json")]

It’s very important that you never add your own binding redirect for Newtonsoft.Json.dll either. Doing so will force all assemblies in the Visual Studio process to redirect to the version you ship. This might lead to unpredictable issues that could end up breaking other extensions and internal components.

Follow the simple rules

So, the simple rules to apply when using Newtonsoft.Json are:

  1. Reference the lowest version of Newtonsoft.Json (but no lower than 6.0.x)
  2. Don’t ship Newtonsoft.Json.dll in the extension
    1. Except if you target Visual Studio 12.0 or older
    2. Except if you absolutely need a newer version than ships in Visual Studio
    3. If you do, specify a code base for it
  3. Don’t ever add binding redirects for Newtonsoft.Json.dll

I wrote this post based on feedback and questions about how to correctly reference Newtonsoft.Json from an extension. I hope it helped clarify it. If not, please let me know in the comments.

Author

Mads Kristensen
Principal Product Manager

Mads Kristensen is a principal program manager on the Visual Studio team and has published over 150 free Visual Studio extensions. He blogs about anything related to Visual Studio and can often be found hosting various shows on the Visual Studio YouTube channel..

12 comments

Discussion is closed. Login to edit/delete existing comments.

  • Adrian Hernandez

    I tried these options, but, still doesn't work. I am trying to use Newtonsoft.json in an SSIS solution via Script Component Task. Follow all these instructions, C# script builds correctly, but each time I run the SSIS package I always get the same errors because Newtonsoft.jston files are not found (Script Component : Runtime Error ... Could not load file or assembly 'Newtonsoft.Json, version =9.0.0.0,...). I tried the latest version 12.2, but the results are...

    Read more
  • Ognyan Dimitrov

    For some reason after updating VS 2019 to 16.1.1 Docker started to crash complaining it can not find Newtonsoft.Json ver 9.0.

  • Christian Matthias

    I thought newtonsoft was going to be baked into the .net framework. Is this not the case? 

  • Matt Whitfield

    The problem with this is that it isn't always practical to reference a lower version - as many third party libraries will force you on to newer versions (even though they don't make use of newer functionality). There is also another dimension to this, which you haven't touched on - which is what framework version we are allowed to reference for different versions. Newtonsoft.Json has literally forever shipped breaking the rules on assembly strong naming...

    Read more
    • Graham Helliwell

      I can't comment on the specific Newtonsoft.Json case. But it's pretty common practice (including from Microsoft) to use the rule that given two published assemblies with the same strong name, one's API is the strict superset of the other. Specifically, the "newer" one with the later package/file version is a superset of the "older" one. Therefore if you compile against the earlier one, you can guarantee that you'll see no MissingMethodExceptions.
      *: Google "c# binary...

      Read more
      • Matt Whitfield

        I understand it's a common practice - but that doesn't mean it is the right thing to do. A program compiled against the DLL with the larger surface area can easily pick up the DLL with the smaller surface area if the latter is installed in the GAC. And you can't necessarily compile against the earlier one all the time. Case in point - ASP.NET MVC 5 - uses Newtonsoft.Json under the hood to do...

        Read more
  • Francesco Colombo

    Hi Mads and thank you for your blog post about VS extensions and Newtonsoft.Json.I'm looking for some help about this topic. I'm currently working on a VS2015 ext which includes SignalR.Core.Client. SignalR use a newer version of NW.Json, so I need to ship my ext with that newer version. Unfortunatelly I'm having no success on this. When I try to connect the SignalR client to a server I get an exception like this:Could not load...

    Read more
  • Jon Miller

    If I remember correctly, Microsoft is giong to be including a new JSON parser in .NET Core 3? One that is more efficient and does less memory alllocations. I'm wondering if VS will be moving to that? I assume not, considering it probably uses features that won't be available to the .NET Framework. Will VS be ported to .NET Core? I'm wondering if the new JSON parser will support schema validation. Newtonsoft charges for this....

    Read more
    • Mads KristensenMicrosoft employee Author

      There are no plans to move to another JSON parser or port VS to .NET Core in the 16.x timeframe.

  • Jon Mikel Inza

    Thanks Mads. Useful and clear.
    This VS strong dependency is pretty understandable. However, is Microsoft working on easing the use of newer Newtonsoft.Json.dll versions (> 9.0.1) for the extensions (as if we were using any other reference/NuGet package)? Having to add the dll directly to the VSIX package does not sound ideal for many reasons.

    • Mads KristensenMicrosoft employee Author

      The version of Newtonsoft.Json will be updated in VS when a internal component needs it. Then we will update Newtonsoft.Json to the latest version. Actually, we’re looking in to updating to version 12 at the moment, but it could take many months before it will be available in an update. 

  • Alin ConstantinMicrosoft employee

    Many thanks! Great timing, just one day later after publishing I needed this info :-). It was driving me crazy why all other referenced assemblies got packed and deployed by vsix for a project I was writing, just not Newtonsoft.Json 12.0. I was already going on the path of adding it explicitly as vsixmanifest asset… Downgrading the nuget package to 9.0.1 saved me some time!