Repro steps:
Error:
Could not load file or assembly 'Newtonsoft.Json, Version=6.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)
Expected:
It should successfully update binding redirects in web.config file and run successfully.
@jainaashish - can you please remind me which versions of NuGet have this problem?
I got the same problem with a non-web application project when updating Moq on all my testing projects recently. This worked flawlessly in 2.0 but not 3.0 it seems. Is this a supported feature?
@rrelyea it's reproing with 3.4.4, 3.5.0-beta2, 3.5.0-rc1, and dev branch. I didn't try it with 3.4.3 or earlier builds.
@Mike-EEE Can you share a sample with your issue which involves non-web app projects? I looked deeper into my case and figured out for a web app project, there are multiple references for newtonsoft.json package in csproj file which causes this issue.
Well I wouldn't say sample, but I have a solution under heavy development that you can check out here:
https://github.com/DevelopersWin/VoteReporter/tree/development
I upgraded from NuGet 2.0 to 3.0, so I am no longer using any references under csproj's (that is, all references are in project.json now -- and work pretty well). Everything works like a champ with the exception of these assembly binding redirects. Moq recently upgraded its version and that is when I ran into this problem.
I have yet to hear from anyone whether this is expected to work in 3.0 as it did in 2.0, however. Sort of confusing and a bit frustrating at this point. :stuck_out_tongue: FWIW, I started my inquiry on a recent NuGet blog post announcing 3.5 RC.
As of now nuget doesn't handle binding redirects for project.json so it will need to be done manually. Work is in progress to get this feature well define and may gets into nuget 3.6
Great, thank you for the clarification, @jainaashish!
Just curious (said the cat :smile_cat:)... is this being tracked with an issue(s) here on GitHub by chance? Or perhaps we should create one?
You can create one for this!
Great. Done:
https://github.com/NuGet/Home/issues/3372
(Thanks again to those who have put in the hard work and hours into 3.0!)
Since this is not our issue, rather template system team and they are working on a fix. So closing this issue.
I've developed a PowerShell script that will update your config file (be it web.config or app.config) based on the packages in your packages.config and the DLL(s) in your BIN directory; so I suggest you run it on a published product.
param (
[Parameter(Mandatory=$false)]
[string] $webConfigPath,
[string] $packagesConfigPath,
[string] $binPath
)
[bool]$isWindowsFormsAssemblyLoaded = $false
[System.Xml.Linq.XNamespace]$ns1 = "urn:schemas-microsoft-com:asm.v1"
function ClearBindings([System.Xml.Linq.XDocument] $xml) {
$elements = $xml.Root.Element("runtime").Element($ns1 + "assemblyBinding").Elements()
$l1 = New-Object "System.Collections.Generic.List[System.Xml.Linq.XElement]"
$l1.AddRange($elements)
$l1 | ForEach-Object { $_.Remove() }
}
function GetPackageList([System.Xml.Linq.XDocument] $xml, [string] $binPath) {
$elements = $xml.Root.Elements("package")
$l1 = New-Object "System.Collections.Generic.List[System.Xml.Linq.XElement]"
$l1.AddRange($elements)
[System.Collections.Generic.List[string]]$packageList = New-Object "System.Collections.Generic.List[string]"
$l1 | ForEach-Object { $packageList.Add("$binPath\" + $_.Attribute("id").Value + ".dll") }
return $packageList
}
function ExtractPublicKey([System.Reflection.Assembly]$asm) {
$bytes = $asm.GetName().GetPublicKeyToken()
return [System.BitConverter]::ToString($bytes).Replace("-", "")
}
function ExtractCulterInfoName($asm) {
if ($asm.GetName().CultureInfo.TextInfo.CultureName -eq "") {
return "neutral"
} else {
return $asm.GetName().CultureInfo.TextInfo.CultureName
}
}
function CreateBindingElement([System.IO.FileInfo] $fi) {
[System.Reflection.Assembly]$asm = [System.Reflection.Assembly]::LoadFile($fi.FullName)
$publicKey = ExtractPublicKey $asm
$culterInfo = ExtractCulterInfoName $asm
$assemblyIdentity = [System.Xml.Linq.XElement]::new($ns1 + "assemblyIdentity")
$assemblyIdentity.Add([System.Xml.Linq.XAttribute]::new("name", $asm.GetName().Name))
$assemblyIdentity.Add([System.Xml.Linq.XAttribute]::new("publicKeyToken", $publicKey))
$assemblyIdentity.Add([System.Xml.Linq.XAttribute]::new("culture", $culterInfo))
$bindingRedirect = [System.Xml.Linq.XElement]::new($ns1 + "bindingRedirect")
$bindingRedirect.Add([System.Xml.Linq.XAttribute]::new("oldVersion", "0.0.0.0-65535.65535.65535.65535"))
$bindingRedirect.Add([System.Xml.Linq.XAttribute]::new("newVersion", $asm.GetName().Version<#$fi.VersionInfo.FileVersion#>))
return [System.Xml.Linq.XElement]::new($ns1 + "dependentAssembly", $assemblyIdentity, $bindingRedirect)
}
function UpdateBindings([string] $webConfigPath, [string] $packageConfigPath, [string] $binPath) {
$webConfig = [System.Xml.Linq.XDocument]::Load($webConfigPath)
ClearBindings $webConfig
[System.Xml.Linq.XDocument] $packageConfig = [System.Xml.Linq.XDocument]::Load($packageConfigPath)
$packages = GetPackageList $packageConfig $binPath
[System.Xml.Linq.XElement]$assemblyBinding = $webConfig.Root.Element("runtime").Element($ns1 + "assemblyBinding")
$packages | ForEach-Object {
[System.IO.FileInfo]$fi = [System.IO.FileInfo]::new($_)
if ($fi.Exists) {
$newElement = CreateBindingElement $fi
$assemblyBinding.Add($newElement)
}
}
$webConfig.Save($webConfigPath)
}
function LoadWindowsFormsAssembly() {
if (!$isWindowsFormsAssemblyLoaded) {
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
$isWindowsFormsAssemblyLoaded = $true
}
}
function PromptForFile ([string]$title, [string]$filter) {
LoadWindowsFormsAssembly
[System.Windows.Forms.OpenFileDialog]$dialog = New-Object System.Windows.Forms.OpenFileDialog
$dialog.Multiselect = $false
$dialog.Title = $title
$dialog.Filter = $filter
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { return $dialog.FileName }
else { return $null }
}
function PromptForDirectory ([string]$title) {
LoadWindowsFormsAssembly
[System.Windows.Forms.FolderBrowserDialog]$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { return $dialog.SelectedPath }
else { return $null }
}
function MessageBox([string]$title) {
LoadWindowsFormsAssembly
[System.Windows.Forms.MessageBox]::Show($title)
}
if ([System.String]::IsNullOrEmpty($webConfigPath)) {
$webConfigPath = PromptForFile 'Please select the web.config file' 'Web Configuration File|web.config|Application Configuration File|app.config'
if ([System.String]::IsNullOrEmpty($webConfigPath)) {exit}
}
if ([System.String]::IsNullOrEmpty($packagesConfigPath)) {
$packagesConfigPath = PromptForFile 'Please select the packages.config file' 'NuGet Package File (packages.config)|packages.config'
if ([System.String]::IsNullOrEmpty($packagesConfigPath)) {exit}
}
if ([System.String]::IsNullOrEmpty($binPath)) {
$binPath = PromptForDirectory "Please select your application's BIN directory"
if ([System.String]::IsNullOrEmpty($binPath)) {exit}
}
UpdateBindings $webConfigPath $packagesConfigPath $binPath
BTW, the Add-BindingRedirect command of the NuGet package console does not work. It only updated 3 of the 72 referenced packages. The asterisks option did not help either (AKA "Add-BindingRedirect *")
Most helpful comment
You can create one for this!