Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems using System.IO.Compression after upgrading from .Net 4.6.1 to .Net 4.8

We have an Asp.Net MVC project that we have recently upgraded from .Net 4.6.1 to .Net 4.8. It has some dependencies on other projects in our solution that have also been upgraded. The MVC project itself uses System.IO.Compression to zip some files as does one of the other projects it depends on.

Since upgrading, we are seeing some strange behaviour with System.IO.Compression. If we build the new solution, it doesn't automatically copy System.IO.Compression.dll and System.IO.Compression.FileSystem.dll to the output bin folder. This causes a runtime exception on the lines of code that tries to do zipping…

System.IO.FileNotFoundException: 'Could not load file or assembly 'System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.'

This is unsurprising I suppose if the dll is not even copied to the bin folder.

If I set the "Copy Local" property to true on the System.IO.Compression.dll and System.IO.Compression.FileSystem.dll in the references of the MVC project, the files are copied from

"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.8" to the bin folder, but the following error is shown in the browser when the application first starts…

[BadImageFormatException: Cannot load a reference assembly for execution.]

[BadImageFormatException: Could not load file or assembly 'System.IO.Compression' or one of its dependencies. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)]
   System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
   System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +232
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection) +113
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +23
   System.Reflection.Assembly.Load(String assemblyString) +35
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +48

[ConfigurationErrorsException: Could not load file or assembly 'System.IO.Compression' or one of its dependencies. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)]
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +767
   System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +256
   System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +58
   System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +287
   System.Web.Compilation.BuildManager.GetPreStartInitMethodsFromReferencedAssemblies() +69
   System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +137
   System.Web.Compilation.BuildManager.ExecutePreAppStart() +172
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +854

[HttpException (0x80004005): Could not load file or assembly 'System.IO.Compression' or one of its dependencies. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +532
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +111
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +724

Curiously, the previous .Net 4.6.1 version that worked, which had Nuget references to System.IO.Compression, copied the files from

"C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib" into the bin folder. If we manually copy these versions of the files into our .Net 4.8 bin folder, the application works without any exceptions.

I have tried various combinations of bindingRedirects in the web.config file, but without success.

I have been reading other StackOverflow questions that seem related, but haven't been able to a) fully understand the issue and b) know how to fix it so that we can successfully run the .Net 4.8 version and zip files.

Any help would be greatly appreciated

like image 626
Simon Williams Avatar asked Sep 19 '25 16:09

Simon Williams


2 Answers

@Charlieface has correctly identified that with .Net 4.8 there is no need to reference any Nuget packages in order to use System.IO.Compression and System.IO.Compression.FileSystem to zip files. To make this work, I uninstalled all Nuget references in the solution for System.IO.Compression and System.IO.Compression.ZipFile. Once the Nuget references had been uninstalled, I ensured that the relevant projects had direct Assembly references to System.IO.Compression and System.IO.Compression.FileSystem (i.e. right-click "Add Reference…" or "Add Assembly Reference…")

I also had to remove any entries for System.IO.Compression.* files from app.confg and web.config files. These app.config and web.config entries had bindingRedirects on that were also causing the issue.

like image 78
Simon Williams Avatar answered Sep 22 '25 08:09

Simon Williams


What I have noticed with this issue, is that NuGet, when updating System.IO.Compression to the version 4.3.0, is updating the web.config to the version 4.2.0.

If I manually edit the web.config, to point the new version from 4.2.0 to 4.3.0 and old version to 4.1.0, everything works.

Please refer to the attached screenshots as reference. Hope this works as it did to me.


NuGet: System.IO.Compression:

NuGet: System.IO.Compression


Web.Config as NuGet updated:

Web.Config as NuGet updated


Web.Config manually updated:

Web.Config manually updated


like image 27
Santiago Aulestia Avatar answered Sep 22 '25 06:09

Santiago Aulestia