为什么 AutogenerateBindingRedirects 不适用于 Visual Studio 2017 中的 Web.config

Why doesn't AutogenerateBindingRedirects work for a Web.config in Visual Studio 2017

我参考了需要 Microsoft.AspNet.WebApi.Client 5.2.4 的 .Net Standard 2.0 库。这有很多依赖项需要重定向才能使用更新的版本。

为了避免 package/dependency 爆炸,我更新了 csproj 文件中的第一个 PropertyGroup:

<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>

我期待 AutoGenerateBindingRedirects 来防止我需要更改 Web.config 以匹配添加的版本。

为什么我仍然需要向我的 Web.config 添加绑定重定向来解决程序集冲突?

根据 https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/how-to-enable-and-disable-automatic-binding-redirection.

,AutoGenerateBindingRedirects 似乎不适用于 Web 项目

检查构建的输出表明绑定重定向是在 Web.config 中生成的。相反,它们位于 $(AssemblyName).dll.config 中。此文件具有来自 Web.config 的原始配置以及绑定重定向。

要将它们放在一起,您可以让 MSBuild 将生成的配置复制回 Web.config。为此,您需要将以下内容添加到 csproj:

<Target Name="AfterBuild">
  <Copy SourceFiles="$(TargetDir)$(AssemblyName).dll.config" DestinationFiles="Web.config" />
</Target>

对于 iis express:在 Web.config 中将 assemblyBinding 部分替换为

  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <linkedConfiguration href="file:{AssemblyName}.dll.config"/>
  </assemblyBinding>

对于 iis 和 iis express:

添加到项目 Scripts\CopyRuntimeSection.ps1

param ($from, $to)
$projectPath = Resolve-Path "$($PSScriptRoot)\..\"

$fromFilePath = "$projectPath$from";
$toFilePath = "$projectPath$to";

$fromFileXml = [xml](Get-Content -Path $fromFilePath -Raw)
$toFileXml = [xml](Get-Content -Path $toFilePath -Raw)

$toFileXml.configuration.runtime.InnerXml = $fromFileXml.configuration.runtime.InnerXml
$toFileXml.Save($toFilePath)

添加到 csproj

  <Target Name="CopyRuntimeSection" AfterTargets="Build">
    <Exec Command="PowerShell -File Scripts\CopyRuntimeSection.ps1 -from $(OutDir)$(AssemblyName).dll.config -to Web.config" />
  </Target>

扩展这个问题的另一个答案,这里有一个支持增量构建并使用绝对路径以获得更大灵活性的解决方案:

将此添加到您的解决方案中的某处(我将其命名为 UpdateBindingRedirect.ps1):

param ($from, $to)

$fromFileXml = [xml](Get-Content -Path $from -Raw)
$toFileXml = [xml](Get-Content -Path $to -Raw)

if ( $toFileXml.configuration.runtime.InnerXml -Ne $fromFileXml.configuration.runtime.InnerXml ) {
    $toFileXml.configuration.runtime.InnerXml = $fromFileXml.configuration.runtime.InnerXml
    $toFileXml.Save($to)
}

将此添加到您的 csproj

  <Target Name="UpdateBindingRedirects" AfterTargets="Build" Inputs="$(OutDir)$(AssemblyName).dll.config" Outputs="$(ProjectDir)Web.config">
    <Message Text="Update binding redirects from $(ProjectDir)$(OutDir)$(AssemblyName).dll.config" />
    <Exec Command="PowerShell -NoLogo -NoProfile -File ..\UpdateBindingRedirects.ps1 -from $(ProjectDir)$(OutDir)$(AssemblyName).dll.config -to $(ProjectDir)Web.config" />
  </Target>

有一个食谱来自

https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb

您可以重新调整用途以自动更新 Web.config 上的绑定重定向。

警告:未测试

  1. 添加一个属性
<PropertyGroup>
 <OverwriteAppConfigWithBindingRedirects>true</OverwriteAppConfigWithBindingRedirects>
</PropertyGroup>
  1. 使用此处定义的构建目标 UpdateConfigWithBindingRedirects https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/blob/main/src/MSBuild.SDK.SystemWeb/Sdk/Sdk.targets
  <Target Name="UpdateConfigWithBindingRedirects" AfterTargets="AfterBuild" Condition="'$(OverwriteAppConfigWithBindingRedirects)'=='true'">
    <ItemGroup>
      <_DllConfig Remove="@(_DllConfig)" />
      <_AppConfig Remove="@(_AppConfig)" />
      <_ConfigFile Remove="@(_ConfigFileHash)" />
      <_DllConfig Include="$(OutDir)$(AssemblyName).dll.config" />
      <_AppConfig Include="web.config" />
    </ItemGroup>
    <GetFileHash Files="@(_DllConfig)">
      <Output TaskParameter="Hash" PropertyName="_DllConfigHash" />
      <Output TaskParameter="Items" ItemName="_DllConfigFileHash" />
    </GetFileHash>
    <GetFileHash Files="@(_AppConfig)">
      <Output TaskParameter="Hash" PropertyName="_AppConfigHash" />
      <Output TaskParameter="Items" ItemName="_AppConfigFileHash" />
    </GetFileHash>
    <ItemGroup>
      <_ConfigFileHash Include="@(_DllConfigFileHash)" />
      <_ConfigFileHash Include="@(_AppConfigFileHash)" />
    </ItemGroup>
    <Message Text="%(_ConfigFileHash.Identity): %(_ConfigFileHash.FileHash)" />
    <Warning Text="Replacing web.config due to changes during compile - This should clear warning MSB3276 on next compile" File="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
    <Copy SourceFiles="$(OutDir)$(AssemblyName).dll.config" DestinationFiles="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
  </Target>