Nuget Update-Package 错误地更新程序集绑定重定向
Nuget Update-Package incorrectly updating assembly binding redirects
我有一个包含单个 dll 的内部 NuGet 包,没有外部 NuGet 包依赖项,也没有 web.config 转换。
然而,当我针对这个特定的 NuGet 在我的项目(class 库和网站)上 运行 更新包时,它会自动更新我的网站 web.config 程序集绑定重定向到 System.Web.Mvc 和 Newtonsoft.Json 的旧 版本。网站 web.config 目前将它们绑定到正在使用的最新版本。
使用 GUI,利用 Manage NuGet packages for Solution...我选择更新此 NuGet 以适用于引用旧版本的适用项目。然后选择更新
这是包管理器的输出: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 command switch,但这似乎对问题没有影响。
关于什么可以在更新包期间转换我的 web.configs(没有显式转换)的任何想法?
编辑:带有 NuGet 3.3.0 的 VS2015 似乎表现得更好......在随机包更新期间,它发现了一个旧的 BAD 绑定重定向并更正了它!
跳过应用绑定重定向现在是 NuGet 3.3.0 中的一个选项:Issue #1147
我有更好的解决办法。因为每次更新我的包时我都必须更新超过 72 个引用,所以我变得非常疯狂,我开发了一个 PowerShell 脚本,它根据 packages.config 中的包和你拥有的 DLL 更新你的 Web.Config发布在 BIN 目录中。
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
在程序包管理器控制台中使用以下命令
PM> Get-Project –All | Add-BindingRedirect
详见https://weblog.west-wind.com/posts/2014/nov/29/updating-assembly-redirects-with-nuget。
我有一个包含单个 dll 的内部 NuGet 包,没有外部 NuGet 包依赖项,也没有 web.config 转换。
然而,当我针对这个特定的 NuGet 在我的项目(class 库和网站)上 运行 更新包时,它会自动更新我的网站 web.config 程序集绑定重定向到 System.Web.Mvc 和 Newtonsoft.Json 的旧 版本。网站 web.config 目前将它们绑定到正在使用的最新版本。
使用 GUI,利用 Manage NuGet packages for Solution...我选择更新此 NuGet 以适用于引用旧版本的适用项目。然后选择更新
这是包管理器的输出: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 command switch,但这似乎对问题没有影响。
关于什么可以在更新包期间转换我的 web.configs(没有显式转换)的任何想法?
编辑:带有 NuGet 3.3.0 的 VS2015 似乎表现得更好......在随机包更新期间,它发现了一个旧的 BAD 绑定重定向并更正了它!
跳过应用绑定重定向现在是 NuGet 3.3.0 中的一个选项:Issue #1147
我有更好的解决办法。因为每次更新我的包时我都必须更新超过 72 个引用,所以我变得非常疯狂,我开发了一个 PowerShell 脚本,它根据 packages.config 中的包和你拥有的 DLL 更新你的 Web.Config发布在 BIN 目录中。
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
在程序包管理器控制台中使用以下命令
PM> Get-Project –All | Add-BindingRedirect
详见https://weblog.west-wind.com/posts/2014/nov/29/updating-assembly-redirects-with-nuget。