Remapping of assembly does not work
Asked Answered
P

1

8

I am getting the MSB3277 error code when I am building my project in VS2015 RC. The full message is:

1>C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1819,5): warning MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.

So I did that, I changed my output to detailed to see what is going on.

My app.config looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Primitives" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="3.9.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

A more detailed errors comes along:

2> Consider app.config remapping of assembly "System.Net.Primitives, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" from Version "3.9.0.0" [] to Version "4.0.0.0" [C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\Facades\System.Net.Primitives.dll] to solve conflict and get rid of warning.

On the app.config bindings, I have tried both 0.0.0.0-4.0.0.0 as oldVersion and specifying an exact oldVersion, but both result in the same way.

When I go to properties of the System.Net.Http.Primitives it says:

  • Runtime version: v4.0.30319
  • Version: 1.5.0.0

It is a Xamarin project, if that matters anyhow.

Poppycock answered 22/10, 2015 at 10:21 Comment(6)
Did you resolve this error?Penicillin
@Penicillin not as of today. I haven't had much Xamarin work done during the last couple of months thoughPoppycock
I got this error in a Xamarin project also. What I did is a bit radical but it worked. I reinstalled the packages Update-Package -reinstall. See how to reinstall packagesShoop
@Elisa the url you have given returns 404. It was 2 years ago when I had this problem and I didn't solve it. The project is gone now so I cannot even test your proposition :/Poppycock
@Poppycock My mistake! Here is the link learn.microsoft.com/en-us/nuget/consume-packages/…. May be useful for someone who might encounter the same issue.Shoop
If this issue cannot be reproduced any more, time to close or delete it.Japhetic
A
0

Assembly binding is a nightmare when you have different versions of this same NuGet. There is three approaches that I use when I have a similar problem.

  1. Consolidation of NuGet packages. Install the latest and missing if possible.
  2. Remove all "assemblyBinding" sections from the code and reinstall all NuGet packages to get a clean version of the current setup.
  3. Use a custom MSBuild task to fix the problem but you really don't want to use it. If you can migrate your project to .NET Core library or just .NET SDK, do it. I had to force remap it all because I had 100+ projects with bindings with the old .NET Framework which I couldn't easily migrate. Maintenance was a nightmare so I created a task based on MSBuild one.
namespace YourNamespace.Sdk
{
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Xml.Linq;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;

    public class GenerateConfigBindingRedirects : Task
    {
        public string ConfigFilePath { get; set; }

        public ITaskItem[] SuggestedBindingRedirects { get; set; }

        public override bool Execute()
        {
            if (this.SuggestedBindingRedirects == null || this.SuggestedBindingRedirects.Length == 0)
            {
                return true;
            }

            var doc = XDocument.Load(this.ConfigFilePath);

            if (doc == null)
            {
                return false;
            }

            var runtimeNode = doc.Root.Nodes().OfType<XElement>().FirstOrDefault(e => e.Name.LocalName == "runtime");

            if (runtimeNode == null)
            {
                runtimeNode = new XElement("runtime");
                doc.Root.Add(runtimeNode);
            }
            else
            {
                return false;
            }

            var ns = XNamespace.Get("urn:schemas-microsoft-com:asm.v1");

            var redirectNodes = from redirect in this.ParseSuggestedRedirects()
                                select new XElement(
                                        ns + "dependentAssembly",
                                        new XElement(
                                            ns + "assemblyIdentity",
                                            new XAttribute("name", redirect.Key.Name),
                                            new XAttribute("publicKeyToken", GetPublicKeyToken(redirect.Key.GetPublicKeyToken())),
                                            new XAttribute("culture", string.IsNullOrEmpty(redirect.Key.CultureName) ? "neutral" : redirect.Key.CultureName)),
                                        new XElement(
                                            ns + "bindingRedirect",
                                            new XAttribute("oldVersion", "0.0.0.0-" + redirect.Value),
                                            new XAttribute("newVersion", redirect.Value)));

            var assemblyBinding = new XElement(ns + "assemblyBinding", redirectNodes);

            runtimeNode.Add(assemblyBinding);
            using (var stream = new StreamWriter(this.ConfigFilePath))
            {
                doc.Save(stream);
            }

            return true;
        }

        private static string GetPublicKeyToken(byte[] bytes)
        {
            var builder = new StringBuilder();
            for (var i = 0; i < bytes.GetLength(0); i++)
            {
                builder.AppendFormat("{0:x2}", bytes[i]);
            }

            return builder.ToString();
        }

        private IDictionary<AssemblyName, string> ParseSuggestedRedirects()
        {
            var map = new Dictionary<AssemblyName, string>();
            foreach (var redirect in this.SuggestedBindingRedirects)
            {
                try
                {
                    var maxVerStr = redirect.GetMetadata("MaxVersion");
                    var assemblyIdentity = new AssemblyName(redirect.ItemSpec);
                    map.Add(assemblyIdentity, maxVerStr);
                }
                catch
                {
                }
            }

            return map;
        }
    }
}
namespace YourNamespace.Sdk
{
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    using Microsoft.Build.Utilities;

    public class RemoveRuntimeNode : Task
    {
        public string ConfigFilePath { get; set; }

        public override bool Execute()
        {
            var doc = XDocument.Load(this.ConfigFilePath);

            if (doc == null)
            {
                return false;
            }

            doc.Root.Nodes().OfType<XElement>().FirstOrDefault(e => e.Name.LocalName == "runtime")?.Remove();

            using (var stream = new StreamWriter(this.ConfigFilePath))
            {
                doc.Save(stream);
            }

            return true;
        }
    }
}

From csproj:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.4.0" />
  </ItemGroup>

  <UsingTask TaskName="RemoveRuntimeNode" AssemblyFile="$([MSBuild]::ValueOrDefault('$(YourLibPath)', '$(MSBuildThisFileDirectory)..\lib\netstandard2.0\YourNamespace.Sdk.dll'))" />

  <UsingTask TaskName="GenerateConfigBindingRedirects" AssemblyFile="$([MSBuild]::ValueOrDefault('$(YourLibPath)', '$(MSBuildThisFileDirectory)..\lib\netstandard2.0\YourNamespace.Sdk.dll'))" />

  <Target Name="RemoveConfigRuntimeNode" BeforeTargets="ResolveAssemblyReferences" Condition="Exists('$(MSBuildProjectDirectory)\app.config')">
    <RemoveRuntimeNode ConfigFilePath="$(MSBuildProjectDirectory)\app.config" />
  </Target>

  <Target Name="GenerateConfigBindingRedirects" AfterTargets="RemoveConfigRuntimeNode" Condition="Exists('$(MSBuildProjectDirectory)\app.config')">
    <GenerateConfigBindingRedirects ConfigFilePath="$(MSBuildProjectDirectory)\app.config" SuggestedBindingRedirects="@(SuggestedBindingRedirects)"/>
  </Target>
</Project>
Amoebaean answered 28/8, 2022 at 11:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.