17

I have a reference to a .Net Standard 2.0 library that requires Microsoft.AspNet.WebApi.Client 5.2.4. This has a lot of dependencies that need to be redirected to use newer versions.

To avoid package/dependency explosion I've updated the first PropertyGroup in the csproj file:

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

I'm expecting AutoGenerateBindingRedirects to prevent me from needing to change the Web.config to match the versions added.

Why do I still need to add binding redirects to my Web.config to resolve assembly conflicts?

Daniel Leach
  • 5,517
  • 4
  • 18
  • 32

4 Answers4

26

It appears that AutoGenerateBindingRedirects will not work for web projects per https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/how-to-enable-and-disable-automatic-binding-redirection.

Inspecting the output from the build shows that binding redirects are generated just not in the Web.config. Instead, they are in $(AssemblyName).dll.config. This file has the original configuration from Web.config as well as the binding redirects.

To put it all together you can have MSBuild copy the resulting config back to the Web.config. To do this you would add the following to the csproj:

<Target Name="AfterBuild">
  <Copy SourceFiles="$(TargetDir)\$(AssemblyName).dll.config" DestinationFiles="Web.config" />
</Target>
Daniel Leach
  • 5,517
  • 4
  • 18
  • 32
  • 2
    Note that there is also some visual studio integration that can update needed binding redirects in Web.config https://github.com/dotnet/standard/issues/613#issuecomment-354393350 – Martin Ullrich Feb 25 '18 at 10:58
  • Daniel, you mentioned that the redirects will in fact be added to the output .dll.config, just not to the source web.config. Is it possible to disable this auto-generation of redirects to the output .dll.config? Because I tried setting the .csproj settings to false for AutoGenerateBindingRedirects and GenerateBindingRedirectsOutputType, but this did not stop them from being auto-generated. – BlueTriangles Sep 22 '18 at 22:50
5

For iis express: In Web.config replace section assemblyBinding with

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

For iis and iis express:

add to project 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)

add to csproj

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

Expanding on the other answer from this question, here's a solution that supports incremental builds and uses absolute paths for greater flexibility:

Add this somewhere in your solution (I named it 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)
}

Add this to your 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>
Bouke
  • 11,768
  • 7
  • 68
  • 102
-1

There is a recipe from

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

that you can repurpose to update binding redirects on Web.config automatically.

Warning: not tested

  1. Add a property
<PropertyGroup>
 <OverwriteAppConfigWithBindingRedirects>true</OverwriteAppConfigWithBindingRedirects>
</PropertyGroup>
  1. Use the build target UpdateConfigWithBindingRedirects as defined here 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>
Chui Tey
  • 5,436
  • 2
  • 35
  • 44