c# - NuGet 包(.NET Standard 2.x)打破 ASP.NET MVC5 应用程序(.NET 完整框架)
问题描述
(更新 - 见下文)
我有一个 ASP.NET MVC5 应用程序(多个程序集)都解决了 .NET Full Framework 4.7.1
我最近添加了一个使用 .NET Standard 2 构建的(私有)NuGet 包。从快速入门:使用 Visual Studio (.NET Framework) 创建和发布包:
除非您有其他选择的理由,否则 .NET Standard 是 NuGet 包的首选目标,因为它提供与最广泛的消费项目的兼容性。
从那以后,事情就不一样了......我在下面提到了一系列错误,但我怀疑它们都是同一个问题的症状(最后讨论)。
请注意:我使用的是 Visual Studio 15.7.1,所有 NuGet 包都使用 package.config 管理格式而不是 PackageReference。
第一个问题
找不到方法:'System.Collections.ObjectModel.Collection`1 System.Web.Http.HttpConfiguration.get_MessageHandlers()'
我的猜测是 System.Web.Http 的 .NET Standard 版本没有此方法,而我的应用程序选择解决此问题而不是 4.7.1 框架。
我通过将以下内容添加到我的 web.config 文件来部分解决此问题:
<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>
我说“部分”修复了它,这解决了在我的 DEV 环境(使用 Visual Studio)中运行时的问题,但是当发布到我们的 QA 环境时,问题仍然存在。有想法该怎么解决这个吗?
注意:MVC 项目对 System.Net.Http 的引用存在于以下路径中(它不是 NuGet 包):
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net471\lib\System.Net.Http.dll
第二个问题 其中两个程序集涉及从各种 Web 源(WCF、web-api、web-service)中提取数据。在 RELEASE 模式下编译这些(我打开了代码分析等)时,我收到以下错误报告:
尝试加载格式不正确的程序集:C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.1\Facades\System.IO.Compression.ZipFile.dll。{程序集的名称} {程序集的路径}\SGEN
我发现一篇帖子有以下建议:
我看到的另一个建议(根本没有帮助我)是禁止项目创建序列化程序集。请按照以下步骤执行此操作(它可能有帮助也可能没有帮助,但值得一试):
- 在解决方案资源管理器中,右键单击有错误的项目并转到属性。
- 在 Build 选项卡中,滚动到最底部并将 Generate Serialization Assembly 更改为 Off
我试过了,是的,它对我有用。然而,这两个项目正在序列化对象以发送到这些不同的 Web 源,所以我想做的最后一件事是在我的应用程序中取消优化序列化......
关于可能出了什么问题,或者我应该如何最好地进行的任何建议?
2018 年 5 月 14 日更新 我发现了来自Scot Hanselman的一篇关于 NuGet 包的精彩文章,其中指出:
正如奥伦明智地说:
“使用 .NET Standard 要求您使用 PackageReference 来消除“大量包”的痛苦,并正确处理传递依赖项。虽然您可以在没有 PackageReference 的情况下使用 .NET Standard,但我不推荐它。”
但是,有一个问题....在 Visual Studio 中,现在有一种简单的方法可以将程序集从旧的 package.config 迁移到 PackageReference,详见此链接,但该文章明确指出:
请注意,迁移器目前不支持 C++、JavaScript 和 ASP.NET (.NET Framework) 项目。
在尝试此操作时,迁移工具适时通知我,对于 NuGet 包 Microsoft.AspNet.Mvc 和 Microsoft.AspNet.WebPages:
迁移后安装软件包时,“内容”资产不可用
2018 年 5 月 23 日更新我发现其他几个人也遇到了类似的问题。来自 GitHub:使用 SGen 构建的 .NET 4.6.1/.NET Standard 2.0 失败 #1630。他们的“解决方案”再次禁用序列化(见上文),这会破坏我的应用程序的性能。
<GenerateSerializationAssemblies>关闭</GenerateSerializationAssemblies>
结论?
那么,我是否可以得出这样的结论:要在 .NET FullFramework 应用程序中使用 .NET Standard 2.x NuGet 包,我需要使用 PackageReference 而不是 package.config,而这目前在 AspNet.MVC 应用程序中是不可能的?换句话说,目前是不可能的。
解决方案
我遇到了 .Net Framework 4.8 应用程序和System.Buffers
程序集格式不正确的问题
MarkKharitonov 的建议已经解决了这个错误。有了Directory.Build.targets
文件,我可以毫无问题地构建一个项目。
<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>