Skip to content

Commit 21e499d

Browse files
authored
Incorporated New BindingRedirect Generation (#36)
This feature offers consuming projects to choose from "Preview", "Overwrite", and "None" behaviours
1 parent 2ea1062 commit 21e499d

6 files changed

Lines changed: 111 additions & 127 deletions

File tree

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,30 @@
11
# Autogenerating Binding Redirects
22

3-
The template will, on compile, generate a copy of the current `web.config` with any required binding redirects added.
4-
This file is written to the `bin` folder with the name `AssemblyName.dll.config` where `AssemblyName` is the name of your assembly.
3+
The template will, on compile, discover any required binding redirects.
54

6-
You can set the `AssemblyName` by adding
7-
```xml
8-
<AssemblyName>MyAssemblyName</AssemblyName>
9-
```
10-
to your project file as normal.
5+
You may see a build warning `Warning MSB3276 Found conflicts between different versions of the same dependent assembly. Please set the "AutoGenerateBindingRedirects" property to true in the project file. For more information, see http://go.microsoft.com/fwlink/?LinkId=294190.`, and one of three possible actions can be taken with these discovered Binding Redirections
116

12-
If you get the error `Warning MSB3276 Found conflicts between different versions of the same dependent assembly. Please set the "AutoGenerateBindingRedirects" property to true in the project file. For more information, see http://go.microsoft.com/fwlink/?LinkId=294190. <project name here>`, then you can manually copy the
7+
## None
8+
If you Would like No Action to be taken with these suggestions, set the `GeneratedBindingRedirectionsAction` to `None` in your project file.
139
```xml
14-
<runtime>
15-
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
16-
...
17-
</assemblyBinding>
18-
</runtime>
10+
<PropertyGroup>
11+
<GeneratedBindingRedirectsAction>None</GeneratedBindingRedirectsAction>
12+
</PropertyGroup>
1913
```
20-
section from the generated `.dll.config` file to your web.config file, replacing the existing `assemblyBinding` node.
21-
22-
Alternatively, since the `.dll.config` file is based on your `web.config` file, you can just overwrite your `web.config` file with the `.dll.config` file.
2314

24-
If you want this to happen automatically, you can add the following to your project file.
15+
## Preview
16+
You can also choose to `Preview` and generate a file `Web.BindingRedirects.config` that contains the suggested Binding Redirects.
2517
```xml
2618
<PropertyGroup>
27-
<OverwriteAppConfigWithBindingRedirects>true</OverwriteAppConfigWithBindingRedirects>
19+
<GeneratedBindingRedirectsAction>Preview</GeneratedBindingRedirectsAction>
2820
</PropertyGroup>
2921
```
3022

31-
This enables the following target in the SDK which will overwrite your web.config from the patched version if there are any changes.
32-
23+
## Overwrite
24+
Alternatively the suggested Binding Redirects can be written directly to the `web.config`.
25+
If you want this to happen automatically, you can add the following to your project file.
3326
```xml
34-
<Target Name="UpdateConfigWithBindingRedirects" AfterTargets="AfterBuild" Condition="'$(OverwriteAppConfigWithBindingRedirects)'=='true'">
35-
<ItemGroup>
36-
<_DllConfig Remove="@(_DllConfig)" />
37-
<_AppConfig Remove="@(_AppConfig)" />
38-
<_ConfigFile Remove="@(_ConfigFileHash)" />
39-
<_DllConfig Include="$(OutDir)$(AssemblyName).dll.config" />
40-
<_AppConfig Include="web.config" />
41-
</ItemGroup>
42-
<GetFileHash Files="@(_DllConfig)">
43-
<Output TaskParameter="Hash" PropertyName="_DllConfigHash" />
44-
<Output TaskParameter="Items" ItemName="_DllConfigFileHash" />
45-
</GetFileHash>
46-
<GetFileHash Files="@(_AppConfig)">
47-
<Output TaskParameter="Hash" PropertyName="_AppConfigHash" />
48-
<Output TaskParameter="Items" ItemName="_AppConfigFileHash" />
49-
</GetFileHash>
50-
<ItemGroup>
51-
<_ConfigFileHash Include="@(_DllConfigFileHash)" />
52-
<_ConfigFileHash Include="@(_AppConfigFileHash)" />
53-
</ItemGroup>
54-
<Message Text="%(_ConfigFileHash.Identity): %(_ConfigFileHash.FileHash)" />
55-
<Warning Text="Replacing web.config due to changes during compile - This should clear warning MSB3276 on next compile" File="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
56-
<Copy SourceFiles="$(OutDir)$(AssemblyName).dll.config" DestinationFiles="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
57-
</Target>
27+
<PropertyGroup>
28+
<GeneratedBindingRedirectsAction>Overwrite</GeneratedBindingRedirectsAction>
29+
</PropertyGroup>
5830
```

docs/Binding_Redirects/How-to-show-Suggested-Binding-Redirects.md

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,12 @@
22

33
The following may be useful if you need to see generated binding redirects.
44
e.g. if you want to manually add them to your `web.config`
5-
```xml
6-
<UsingTask TaskName="ShowBindingRedirects" TaskFactory="$(TaskFactory)" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
7-
<ParameterGroup>
8-
<SuggestedBindingRedirects ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
9-
</ParameterGroup>
10-
<Task>
11-
<Using Namespace="System" />
12-
<Using Namespace="System.IO" />
13-
<Using Namespace="System.Reflection" />
14-
<Using Namespace="System.Xml" />
15-
<Using Namespace="Microsoft.Build.Framework" />
16-
<Code Type="Fragment" Language="cs">
17-
<![CDATA[
18-
StringBuilder sb = new StringBuilder();
19-
foreach(var sbr in SuggestedBindingRedirects) {
20-
var an = new AssemblyName(sbr.ItemSpec);
21-
var mvn = sbr.GetMetadata("MaxVersion");
225

23-
byte []pt = an.GetPublicKeyToken();
24-
25-
sb.AppendLine("<assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">");
26-
sb.AppendLine("\t<dependentAssembly>");
27-
sb.Append("\t\t<assemblyIdentity name=\"");
28-
sb.Append(an.Name);
29-
sb.Append("\" publicKeyToken=\"");
30-
if (pt is null) {
31-
sb.Append("null");
32-
} else {
33-
for (int i=0;i<pt.GetLength(0);i++)
34-
sb.AppendFormat("{0:x2}", pt[i]);
35-
}
36-
sb.Append("\" culture=\"");
37-
sb.Append(an.CultureName);
38-
sb.AppendLine("\" />");
39-
sb.Append("\t\t<bindingRedirect oldVersion=\"0.0.0.0-");
40-
sb.Append(mvn);
41-
sb.Append("\" newVersion=\"");
42-
sb.Append(mvn);
43-
sb.AppendLine("\" />");
44-
sb.AppendLine("\t</dependentAssembly>");
45-
sb.AppendLine("</assemblyBinding>");
46-
}
47-
Log.LogMessage(MessageImportance.High,sb.ToString());
48-
]]>
49-
</Code>
50-
</Task>
51-
</UsingTask>
6+
Add this into your csproj
7+
```xml
8+
<PropertyGroup>
9+
<GeneratedBindingRedirectsAction>Preview</GeneratedBindingRedirectsAction>
10+
</PropertyGroup>
11+
```
5212

53-
<Target Name="ShowBindingRedirects" AfterTargets="ResolveAssemblyReferences">
54-
<ShowBindingRedirects SuggestedBindingRedirects="@(SuggestedBindingRedirects)" Condition="'@(SuggestedBindingRedirects)'!=''" />
55-
</Target>
56-
```
13+
And then look for a `Web.BindingRedirects.config` file in your project's Solution Explorer.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<!--
2+
====================================================================================================
3+
4+
GenerateBindingRedirects Behaviors
5+
6+
Traditionally (Microsoft.Common.CurrentVersion.targets) only Performs BindingRedirect calculations when
7+
Project type is deemed to "need" redirects -> when OutputType == 'exe' or OutputType == 'winexe' (Microsoft.Common.CurrentVersion.targets)
8+
AND
9+
Not an "old" project, aka either
10+
An SDK project type that incorporates Microsoft.NET.Sdk (Microsoft.NET.Sdk.BeforeCommon.targets)
11+
OR
12+
A newer Full Framework project TargetFrameworkIdentifier == '.NETFramework' and '$(TargetFrameworkVersion.TrimStart(vV))' >= '4.7.2' (Microsoft.Common.CurrentVersion.targets)
13+
Additionally it chooses the filename of the config file to be updated as what exe projects want...
14+
$(IntermediateOutputPath)$(TargetFileName).config -> the config file named after the assembly and in the IntermediateOutputPath
15+
16+
https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/issues/34
17+
This SDK Project Type will override these settings so that we can facilitate developers working with BindingRedirects in the web.config
18+
Enable the Build Process to calculate Binding Redirects
19+
GenerateBindingRedirectsOutputType(true - even though this project is not an .exe or .winexe)
20+
AutoGenerateBindingRedirects (true - set explictly even though should be set by Microsoft.NET.Sdk.BeforeCommon.targets)
21+
Take an action
22+
OverwriteAppConfigWithBindingRedirects -> this is the SystemWeb Sdk Legacy property
23+
GeneratedBindingRedirectsAction (Overwrite) -> this will conditionally change wich config file is written to
24+
====================================================================================================
25+
-->
26+
27+
<Project>
28+
29+
<PropertyGroup Label="Change the default BindingRedirects behavior for projects of this SDK type">
30+
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
31+
<AutoGenerateBindingRedirects Condition=" '$(AutoGenerateBindingRedirects)' == '' ">true</AutoGenerateBindingRedirects>
32+
</PropertyGroup>
33+
34+
<PropertyGroup Label="Set the desire default behavior of what to do with SuggestedBindingRedirects if not yet set"
35+
Condition=" '$(GeneratedBindingRedirectsAction)' == ''">
36+
<GeneratedBindingRedirectsAction>None</GeneratedBindingRedirectsAction>
37+
<GeneratedBindingRedirectsAction Condition=" '$(OverwriteAppConfigWithBindingRedirects)' != 'true' ">Preview</GeneratedBindingRedirectsAction>
38+
<GeneratedBindingRedirectsAction Condition=" '$(OverwriteAppConfigWithBindingRedirects)' == 'true' ">Overwrite</GeneratedBindingRedirectsAction>
39+
</PropertyGroup>
40+
41+
42+
<!--
43+
====================================================================================================
44+
45+
SystemWebProject_ChooseConfigFileForGenerateBindingRedirects
46+
47+
This target should executes between
48+
ResolveAssmblyReferences (where the "@(SuggestedBindingRedirects)" itemgroup is populated... based on the logic that resolves assemblies being referenced
49+
and
50+
GenerateBindingRedirects (where the suggestedBindingRedirects are written to disk into a config file at $(_GenerateBindingRedirectsIntermediateAppConfig)
51+
52+
Then we can choose where the suggestedBindingRedirects are written, if at all (Default Value is Overwrite unless set by project)
53+
'$(GeneratedBindingRedirectsAction)' == 'Preview' -> Creates new Web.BindingRedirects.config file showing proposed changes
54+
'$(GeneratedBindingRedirectsAction)' == 'Overwrite' -> Updates the $(AppConfig) aka web.config in the project root
55+
'$(GeneratedBindingRedirectsAction)' == Something Unknown -> Prints message giving options of what the developer can choose from
56+
57+
In general we want to emit a "warning" whenever we either do, or don't do something to help developers find the property that drives this behavior
58+
====================================================================================================
59+
-->
60+
<Target Name="SystemWebProject_ChooseConfigFileForGenerateBindingRedirects"
61+
BeforeTargets="GenerateBindingRedirects"
62+
Condition="'$(AutoGenerateBindingRedirects)' == 'true' and '$(GenerateBindingRedirectsOutputType)' == 'true' and @(SuggestedBindingRedirects->Count()) > 0 ">
63+
64+
<PropertyGroup Label="Set the location of the file to which the suggestedBindingRedirects should be written during the GenerateBindingRedirects Target">
65+
<_GenerateBindingRedirectsIntermediateAppConfig Condition="'$(GeneratedBindingRedirectsAction)' == 'Preview' " >Web.BindingRedirects.config</_GenerateBindingRedirectsIntermediateAppConfig>
66+
<_GenerateBindingRedirectsIntermediateAppConfig Condition="'$(GeneratedBindingRedirectsAction)' == 'Overwrite' " >$(AppConfig)</_GenerateBindingRedirectsIntermediateAppConfig>
67+
</PropertyGroup>
68+
69+
<Warning Condition="'$(GeneratedBindingRedirectsAction)' != 'Preview' and '$(GeneratedBindingRedirectsAction)' != 'Overwrite'"
70+
Text="Generated Binding Redirects have been applied only to the $(TargetFileName).config. You should incorporate them into the web.config. Consider setting &lt;GeneratedBindingRedirectsAction&gt;Preview&lt;/GeneratedBindingRedirectsAction&gt; to create a file containing the proposals. Consider setting &lt;GeneratedBindingRedirectsAction&gt;Overwrite&lt;/GeneratedBindingRedirectsAction&gt; to automatically update web.config with proposals." />
71+
72+
<Warning Condition="'$(GeneratedBindingRedirectsAction)' == 'Preview'"
73+
Text="Generated Binding Redirects have been applied only to the Web.BindingRedirects.config. You should incorporate them into the web.config. Consider setting &lt;GeneratedBindingRedirectsAction&gt;Overwrite&lt;/GeneratedBindingRedirectsAction&gt; to automatically update web.config with proposals." />
74+
75+
<Warning Condition="'$(GeneratedBindingRedirectsAction)' == 'Overwrite'"
76+
Text="Generated Binding Redirects have been applied automatically to the web.config. This warning will disappear on the next build." />
77+
78+
</Target>
79+
80+
81+
82+
</Project>

src/MSBuild.SDK.SystemWeb/Sdk/MSBuild.SDK.SystemWeb.DefaultItems.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
<ItemGroup Condition="'$(EnableWebFormsDefaultItems)'=='true'">
1010
<Content Include="Web.config" />
1111
<_WebConfigConfigurations Include="$(Configurations)" />
12-
<None Include="@(_WebConfigConfigurations->'Web.%(Identity).config')">
12+
<None Include="@(_WebConfigConfigurations->'Web.%(Identity).config');Web.BindingRedirects.config">
1313
<DependentUpon>Web.config</DependentUpon>
1414
</None>
15-
<Content Include="Web.*.config" Exclude="@(_WebConfigConfigurations->'Web.%(Identity).config')">
15+
<Content Include="Web.*.config" Exclude="@(None)">
1616
<DependentUpon>Web.config</DependentUpon>
1717
</Content>
1818
</ItemGroup>

src/MSBuild.SDK.SystemWeb/Sdk/Sdk.props

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
<PublishProfileImported>true</PublishProfileImported>
99
<AppConfig>web.config</AppConfig>
1010

11-
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
12-
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
1311
</PropertyGroup>
1412
<ItemGroup>
1513
<ProjectCapability Include="DotNetCoreWeb" />
@@ -18,10 +16,6 @@
1816
<ProjectCapability Include="LegacyRazorEditor" />
1917
</ItemGroup>
2018

21-
<PropertyGroup>
22-
<OverwriteAppConfigWithBindingRedirects Condition="'$(OverwriteAppConfigWithBindingRedirects)'==''">false</OverwriteAppConfigWithBindingRedirects>
23-
</PropertyGroup>
24-
2519
<Import Project="MSBuild.SDK.SystemWeb.DefaultPackages.props" />
2620
<!-- Default item includes -->
2721
<Import Project="MSBuild.SDK.SystemWeb.DefaultItems.props" />

src/MSBuild.SDK.SystemWeb/Sdk/Sdk.targets

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,13 @@
2020
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
2121
</PropertyGroup>
2222

23-
<Target Name="UpdateConfigWithBindingRedirects" AfterTargets="AfterBuild" Condition="'$(OverwriteAppConfigWithBindingRedirects)'=='true'">
24-
<ItemGroup>
25-
<_DllConfig Remove="@(_DllConfig)" />
26-
<_AppConfig Remove="@(_AppConfig)" />
27-
<_ConfigFile Remove="@(_ConfigFileHash)" />
28-
<_DllConfig Include="$(OutDir)$(AssemblyName).dll.config" />
29-
<_AppConfig Include="web.config" />
30-
</ItemGroup>
31-
<GetFileHash Files="@(_DllConfig)">
32-
<Output TaskParameter="Hash" PropertyName="_DllConfigHash" />
33-
<Output TaskParameter="Items" ItemName="_DllConfigFileHash" />
34-
</GetFileHash>
35-
<GetFileHash Files="@(_AppConfig)">
36-
<Output TaskParameter="Hash" PropertyName="_AppConfigHash" />
37-
<Output TaskParameter="Items" ItemName="_AppConfigFileHash" />
38-
</GetFileHash>
39-
<ItemGroup>
40-
<_ConfigFileHash Include="@(_DllConfigFileHash)" />
41-
<_ConfigFileHash Include="@(_AppConfigFileHash)" />
42-
</ItemGroup>
43-
<Message Text="%(_ConfigFileHash.Identity): %(_ConfigFileHash.FileHash)" />
44-
<Warning Text="Replacing web.config due to changes during compile - This should clear warning MSB3276 on next compile" File="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
45-
<Copy SourceFiles="$(OutDir)$(AssemblyName).dll.config" DestinationFiles="web.config" Condition="'$(_DllConfigHash)'!='$(_AppConfigHash)'" />
46-
</Target>
47-
4823
<!-- Default item excludes -->
4924
<Import Project="MSBuild.SDK.SystemWeb.DefaultItems.targets" />
5025

5126
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
27+
28+
<!-- Inject BindingRedirects targets after Microsoft.NET.Sdk is injected -->
29+
<Import Project="MSBuild.SDK.SystemWeb.BindingRedirects.targets" />
30+
5231
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" />
5332
</Project>

0 commit comments

Comments
 (0)