Home: update package failed to update binding redirects on a web application project

Created on 11 Aug 2016  路  13Comments  路  Source: NuGet/Home

Repro steps:

  1. Create a new asp.net web application project
  2. build and run, it will run successfully.
  3. open PM UI and update newtonsoft.json package to latest
  4. Now build and run, it will show below error. And the root cause is after updating newtonsoft.json package, it doesn't update it's binding redirects in web.config.

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.

External

Most helpful comment

You can create one for this!

All 13 comments

@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 *")

Was this page helpful?
0 / 5 - 0 ratings