Nuget Update-Package 错误更新程序集绑定重定向

20
我有一个内部NuGet包,其中包含单个dll,没有外部NuGet包依赖,也没有web.config转换。
但是,当我在我的项目(类库和网站)中的此特定NuGet上运行Update-Package时,它会自动将我的网站web.config程序集绑定重定向更新为旧版的System.Web.Mvc和Newtonsoft.Json。 网站web.config当前将它们绑定到正在使用的最新版本。
使用GUI,利用“解决方案的管理NuGet包”...我选择更新适用于具有对旧版本的引用的项目的此NuGet。然后选择更新
这是Package Manager的输出:http://pastebin.com/3ySwTRFR 我的web.config从这里开始:
  <dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
  </dependentAssembly>

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

收件人:

  <dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
  </dependentAssembly>

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

我正在更新的NuGet包含一个引用了Newtonsoft.Json的dll(但未明确作为NuGet包依赖项)。
当不知情的开发人员更新此NuGet包时,它会破坏运行时,寻找旧版本的MVC或JSON.NET dll。
过去我曾尝试使用-IgnoreDependencies powershell命令开关,但这似乎对问题没有影响。
有任何想法可以在update-package期间转换我的web.configs(没有显式的转换)吗?
编辑:VS2015 w/ NuGet 3.3.0似乎表现更好了...在随机包更新期间,它找到了一个旧的BAD绑定重定向并进行了纠正! enter image description here
3个回答

18

太好了!我不知道这个CMD,虽然我的问题是NuGet在第一次混淆工作重定向时出了问题,所以不应用它们对我有用。 - felickz
当我运行时,NuGet会继续使用包的旧版本(在我的情况下为Microsoft.IdentityModel.Tokens)。所有我的项目都引用了 5.6.0 但它仍然添加了对 5.5.0 的绑定重定向。真是气人。 - Dai

17
现在在NuGet 3.3.0中有一个选项可以跳过应用绑定重定向:问题#1147

输入图像描述


4

我有一个更好的解决方案。每次更新软件包时,我总是需要更新72个以上的引用,这让我感到非常困扰。所以我开发了一个PowerShell脚本,它可以根据您的packages.config文件和BIN目录中发布的DLL文件来更新Web.Config文件。

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' '.NET Configuration File (web.config)|web.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

顺便提一下,Add-BindingRedirect软件包控制台命令不起作用。它只更新了72个引用包中的3个。我提供的脚本遍历所有这些包,并对“packages.config”中的任何包执行操作,除非在BIN目录中存在DLL文件。 - RashadRivera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接