首页 > 解决方案 > 您可以将针对完整框架的包导入 ASP.NET Core 3+ 应用程序吗?

问题描述

我的理解是,从 ASP.NET Core 3.0 开始,.NET Framework 是一个不受支持的目标框架,因此您只能在 .NET Core 运行时上运行。

如果是这种情况,可以将哪些 NuGet 包导入 ASP.NET Core 3 应用程序?

我假设您可以引用任何netstandardnet45.

如果您导入的包引用了一个不属于 .NET Core 的程序集(即 .NET Core),会发生System.Drawing什么?

标签: asp.net-core.net-standardasp.net-core-3.0

解决方案


TL;DR:您仍然可以从 .NET Core 3 甚至 .NET 5 引用(依赖于的包).NET Framework 程序集,但是如果您调用任何不依赖于 API 或库的代码(然而)受 .NET Core 支持。您可以使用 Microsoft 的.NET Portability Analyzer发现这些


背景

首先,正如微软在 2018 年宣布的那样, ASP.NET Core 3.x 应用程序不能再以 .NET Framework 为目标是正确的。该功能以前允许 ASP.NET Core 应用程序调用 .NET Framework 库,从而为迁移到 .NET Core 的 Web 应用程序提供了中间解决方案。

注意:由于 .NET Framework 仅在 Windows 机器上运行,因此编写以 .NET Framework 为目标的 ASP.NET Core Web 应用程序会隐式限制这些应用程序在 Windows 上运行。

行为

但是,即使面向 .NET Core 或现在的 .NET 5,您仍然可以引用 .NET Framework 包和程序集,前提是您在 Windows 计算机上并安装了相应的 .NET Framework。其内部工作有点复杂,但不足之处在于.NET Core 和 .NET 5 将评估 .NET Framework 程序集,就好像它们是.NET 标准程序集一样。如果 API 调用也在.NET Core 运行时中实现,它会正常工作,但如果 API 调用完全是 .NET Framework 的一部分,您将收到异常。

惊喜!强调这是一个运行时异常非常重要。您仍然可以引用 .NET Framework 程序集,编写对有问题的成员的调用,并在没有任何警告的情况下编译您的代码。但是,只要调用依赖于 .NET Framework 特定程序集的代码,就会收到运行时异常。

例子

使用 .NET 3.0,.NET Framework 库的重要部分已移植到 .NET Core。事实上,这包括System.Drawing您作为示例引用的大部分库——尽管您可能有充分的理由不想使用它们。但是,如果您再深入一点,就会发现很多库仍然不受支持。一个明显的例子是WebConfigurationManager,它可用于从web.config文件访问配置设置。

.NET 框架代码

因此,例如,假设您在 .NET Framework 类库中有以下函数,该函数从您的 s 元素返回一个键web.config数组<AppSetting>

public static class Configuration
{
    public static string[] GetAppSettings() => System.Web.Configuration.WebConfigurationManager.AppSettings.AllKeys;
}

ASP.NET 核心代码

然后,在 ASP.NET Core 控制器中,您公开一个端点以检索此数据:

public class MyController: Controller 
{
    public IActionResult ApplicationKeys() => Content(String.Join(", ", Configuration.GetAppSettings()));
}

例外

在面向 .NET Framework 的 ASP.NET Core 2.x 应用程序中,这将正常工作。但是,在 ASP.NET Core 3.x 或 ASP.NET Core 5 应用程序中,调用/My/ApplicationKeys/路由时会收到以下运行时错误:

System.TypeLoadException:'无法从程序集'System.Web,Version = 4.0.0.0,Culture = Neutral,PublicKeyToken = b03f5f7f11d50a3a'加载类型'System.Web.Configuration.WebConfigurationManager'。'

避免意外

如果你和我一样,这会让你非常紧张。当您尝试调用依赖于不受支持的代码的库时,您更愿意收到设计时错误,或者至少是编译时警告。幸运的是,Microsoft 提供了一个.NET Portability Analyzer,它也可以作为 Visual Studio Extension提供,正是为了这个目的。

从 .NET 5 开始,SDK 中还内置了一个兼容性分析器,它将识别特定平台上 .NET 5 运行时不支持的调用。这要求目标库使用该[SupportedOSPlatform()]属性显式注释其类型,因此您不会收到任何有关旧版 .NET Framework 类型的警告。但这将有助于识别针对各种平台的库的类似类型的兼容性问题。

例子

例如,如果您在上面的示例代码上运行 Portability Analyzer,它将输出一个 Excel 电子表格,标识在 eg或T:System.Web.Configuration.WebConfigurationManager不受支持.NET Core,Version=v3.1.NET Standard + Platform Extensions,Version=v2.0

注意:微软曾经以 NuGet 包的形式提供API分析器它承诺在 Visual Studio 中提供设计时分析。可惜代码已经两年没有更新了,最新的版本是 0.2.12-alpha。在我的评估中,它不能有效地识别问题。

示例项目

在 GitHub 上整理了一个示例项目,演示了上述行为。它包括以下项目:

两个 ASP.NET Core 网站都包含两个端点,它们调用相同的 .NET Framework 4.8 类库。第一个是“Hello world”示例,它可以在两个项目上正常执行,因为它完全依赖于通用 API:

http://localhost:5000/Basic/Index

第二个将在 ASP.NET Core 3.1 项目中失败,因为它调用了旧版WebConfigurationManagerAPI:

http://localhost:5000/Basic/Configuration

免责声明:这是一个快速而肮脏的存储库,我在发布之前将其放在一起以验证我的理解。如果有兴趣,我会整理并记录下来。然而,就目前而言,它可能对那些需要看到这一点的人有用。

致谢

@Chris Pratt去年提供了一个很好的答案,涵盖了类似的材料。值得一读。


推荐阅读