Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NuGet package (.NET Standard 2.x) breaking ASP.NET MVC5 application (.NET full framework)

(updated - see below)

I have an ASP.NET MVC5 application (multiple Assemblies) all addressing the .NET Full Framework 4.7.1

I recently added a (private) NuGet package that we built using .NET Standard 2. From Quickstart: Create and publish a package using Visual Studio (.NET Framework):

Unless you have a reason to choose otherwise, .NET Standard is the preferred target for NuGet packages, as it provides compatibility with the widest range of consuming projects.

Since then, things just haven't been the same.....there are a list of errors that I mention below, but I suspect they're all symptoms of the same issue (discussed at the end).

Please note: I'm using Visual Studio 15.7.1, and all NuGet packages use the package.config manage format rather than PackageReference.

First problem

Method not found: 'System.Collections.ObjectModel.Collection`1 System.Web.Http.HttpConfiguration.get_MessageHandlers()'

My guess here is that there's a .NET Standard version of System.Web.Http that doesn't have this method, and my application has chosen to address this rather than the 4.7.1 framework.

I partially fixed this by adding the following to my web.config file:

<dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>

I say "partially" fixed it, this fixes the problem when run in my DEV environment (with Visual Studio) but when published to our QA environment, the issue remains. Any ideas on how to fix this?

Note: The MVC project's reference to System.Net.Http exists in the following path (it is NOT a NuGet package):

C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net471\lib\System.Net.Http.dll

Second problem Two of the Assemblies are involved with pulling data from various web-sources (WCF, web-api, web-service). When compiling these in RELEASE mode (where I have code analysis etc turned on) I get the following error reported:

An attempt was made to load an assembly with an incorrect format: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.1\Facades\System.IO.Compression.ZipFile.dll. {Name of the assembly} {Path to the assembly}\SGEN

I found one post had the following suggestion:

Another suggestion I saw (which didn’t help me at all), was to disable the project from creating a serialization assembly. Follow these steps to do that (it may or may not help, but it’s worth a try):

  1. In Solution Explorer, right click on the project that has the error and go to Properties.
  2. In the Build tab, scroll to the very bottom and change Generate Serialization Assembly to Off

I tried this and yes, it worked for me. However, these are the two projects that are serializing objects to send to these various web sources, so the last thing I want to be doing is un-optimizing serialization within my application...

Any suggestions on what might be wrong, or how I should best proceed?

UPDATE 14-May-2018 I found a great article from Scot Hanselman regarding NuGet packages which states:

As Oren wisely says:

"Using .NET Standard requires you to use PackageReference to eliminate the pain of “lots of packages” as well as properly handle transitive dependencies. While you may be able to use .NET Standard without PackageReference, I wouldn’t recommend it."

However, there's a catch.... In Visual Studio, there is now an easy way to migrate an assembly from the older package.config to PackageReference as detailed in this link, but that article clearly states:

Note that the migrator does not presently support C++, JavaScript, and ASP.NET (.NET Framework) projects.

And when attempting this, the migration tool duly notified me that for the NuGet packages Microsoft.AspNet.Mvc and Microsoft.AspNet.WebPages:

"content" assets are not available when the package is installed after the migration

UPDATE 23-May-2018 I found several other people are experiencing a similar issue. From GitHub: .NET 4.6.1/.NET Standard 2.0 build with SGen fails #1630. Their "solution" was again to disable the serialization (see above) which would ruin performance on my application.

<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>

Conclusion?

So, am I right to conclude that to consume a .NET Standard 2.x NuGet package in a .NET FullFramework application, I need to use PackageReference rather than package.config and this is currently not possible with AspNet.MVC applications? In other words, it's not currently possible.

like image 242
DrGriff Avatar asked May 10 '18 15:05

DrGriff


1 Answers

I've got this problem with .Net Framework 4.8 application and System.Buffers assembly incorrect format

The MarkKharitonov advice has solved the error. With Directory.Build.targets file I can built a project without any problem.

<Project>
  <ItemGroup>
    <ReflectionOnlyAssemblyNames Include="Microsoft.Bcl.AsyncInterfaces"/>
    <ReflectionOnlyAssemblyNames Include="System.Buffers"/>
    <ReflectionOnlyAssemblyNames Include="System.Numerics.Vectors"/>
    <ReflectionOnlyAssemblyNames Include="System.Runtime.CompilerServices.Unsafe"/>
  </ItemGroup>
  <Target Name="RemoveDesignTimeFacadesBeforeSGen" BeforeTargets="GenerateSerializationAssemblies">
    <ItemGroup>
      <_ReflectionOnlyAssembly_Names Include="@(_ReferencePath_Names)"
                                     Condition="'@(ReflectionOnlyAssemblyNames)' == '@(_ReferencePath_Names)' And '%(Identity)' != ''"/>
    </ItemGroup>
    <ItemGroup>
      <ReferencePath Remove="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
      <ReferencePath Remove="@(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Removing DesignTimeFacades from ReferencePath before running SGen." />
  </Target>
  <Target Name="ReAddDesignTimeFacadesBeforeSGen" AfterTargets="GenerateSerializationAssemblies">
    <ItemGroup>
      <ReferencePath Include="@(_DesignTimeFacadeAssemblies_Names->'%(OriginalIdentity)')" />
      <ReferencePath Include="@(_ReflectionOnlyAssembly_Names->'%(OriginalIdentity)')" />
    </ItemGroup>
    <Message Importance="normal" Text="Adding back DesignTimeFacades from ReferencePath now that SGen has run." />
  </Target>
</Project>
like image 189
oleksa Avatar answered Sep 27 '22 17:09

oleksa