使用类库中的 ASP.NET Core API

作者:Scott Addie

此文档提供了关于如何使用类库中的 ASP.NET Core API 的指南。 若要查看所有其他的库指南,请参阅开放源代码库指南

确定要支持哪些 ASP.NET Core 版本

ASP.NET Core 遵从 .NET Core 支持策略。 确定库要支持哪些 ASP.NET Core 版本时,请参阅支持策略。 库应符合以下条件:

  • 努力支持列为“长期支持”(LTS) 类别的所有 ASP.NET Core 版本。
  • 无需支持列为“生命周期结束”(EOL) 类别的 ASP.NET Core 版本。

由于 ASP.NET Core 预览版已推出,因此已在 aspnet/Announcements GitHub 存储库中发布中断性变更。 开发框架功能时,可执行库兼容性测试。

使用 ASP.NET Core 共享框架

随着 .NET Core 3.0 发布,许多 ASP.NET Core 程序集不再作为包发布到 NuGet。 而是改为将这些程序集包含在通过 .NET Core SDK 和运行时安装程序安装的 Microsoft.AspNetCore.App 共享框架中。 若要查看不再发布的包列表,请参阅删除过时的包引用

自 .NET Core 3.0 起,使用 Microsoft.NET.Sdk.Web MSBuild SDK 的项目隐式引用此共享框架。 使用 Microsoft.NET.SdkMicrosoft.NET.Sdk.Razor SDK 的项目必须引用 ASP.NET Core,才能使用共享框架中的 ASP.NET Core API。

若要引用 ASP.NET Core,请将以下 <FrameworkReference> 元素添加到项目文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

包括 Blazor 扩展性

Blazor 支持为服务器端和客户端应用创建 Razor 组件 类库。 若要支持某个类库中的 Razor 组件,该类库必须使用 Microsoft.NET.SdkRazor。SDK

支持服务器端和客户端应用

若要支持服务器端应用和客户端应用都能使用来自一个库的 Razor 组件,请按以下说明操作编辑器。

使用 Razor 类库项目模板。

注意

不要选中“支持页面和视图”复选框。 选中该复选框会得到一个仅支持服务器端应用的类库。

从项目模板生成的库:

  • 基于已安装的 SDK 面向当前的 .NET Framework。
  • 通过 SupportedPlatform MSBuild 项目将 browser 包括在内作为支持的平台,启用对平台依赖项的浏览器兼容性检查。
  • 添加对 Microsoft.AspNetCore.Components.Web 的 NuGet 包引用。

RazorClassLibrary-CSharp.csproj(引用源)

注意

指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)

支持多个框架版本

如果库必须支持当前版本向 Blazor 添加的功能,同时还要支持一个或多个早期版本,则让库面向多个目标。 在 TargetFrameworks MSBuild 属性中提供以分号分隔的目标框架名字对象 (TFM) 列表:

<TargetFrameworks>{TARGET FRAMEWORKS}</TargetFrameworks>

在前面的示例中,{TARGET FRAMEWORKS} 占位符表示以分号分隔的 TFM 列表。 例如 netcoreapp3.1;net5.0

仅支持服务器端使用

很少有仅支持服务器端应用的类库。 如果类库仅需要特定于服务器端的功能(如访问 CircuitHandlerMicrosoft.AspNetCore.Components.Server.ProtectedBrowserStorage),或使用特定于 ASP.NET Core 的功能(如中间件、MVC 控制器或 Razor Pages),请使用以下方法之

  • 使用“支持页面和视图”复选框 (Visual Studio) 或使用 dotnet new 命令搭配 -s|--support-pages-and-views 选项创建库时,指定库支持页面和视图:

    dotnet new razorclasslib -s
    
  • 仅提供对库项目文件中 ASP.NET Core 的框架引用以及对任何其他必需的 MS 生成属性的框架引用:

    <ItemGroup>
      <FrameworkReference Include="Microsoft.AspNetCore.App" />
    </ItemGroup>
    

有关包含 Razor 组件的库的详细信息,请参阅使用 Razor 类库 (RCL) 中的 ASP.NET Core Razor 组件

包括 MVC 扩展性

此部分概述了针对包括以下内容的库的建议:

此部分未探讨用于支持多个 MVC 版本的多目标。 若要查看关于支持多个 ASP.NET Core 版本的指南,请参阅支持多个 ASP.NET Core 版本

Razor 视图或 Razor 页面

包括 Razor 视图Razor 页面的项目必须使用 Microsoft.NET.Sdk.RazorSDK

若项目面向 .NET Core 3.x,它必须满足以下要求:

  • AddRazorSupportForMvc MSBuild 属性设置为 true
  • 具有针对共享框架的 <FrameworkReference> 元素。

Razor 类库项目模板满足以 .NET Core 为目标的项目的上述要求。 请针对自己的编辑器使用以下说明。

使用 Razor 类库项目模板。 应选中此模板的“支持页和视图”复选框。

例如:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

若项目改为面向 .NET Standard,则需要 Microsoft.AspNetCore.Mvc 包引用。 Microsoft.AspNetCore.Mvc 包移到了 ASP.NET Core 3.0 的共享框架中,因此不再发布。 例如:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
  </ItemGroup>

</Project>

标记帮助程序

包含标记帮助器的项目应使用 Microsoft.NET.Sdk SDK。 若面向 .NET Core 3.x,则添加针对共享框架的 <FrameworkReference> 元素。 例如:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

若面向 .NET Standard(以支持 ASP.NET Core 3.x 之前的版本),则添加对 Microsoft.AspNetCore.Mvc.Razor 的包引用。 Microsoft.AspNetCore.Mvc.Razor 包移到了共享框架,因此不再发布。 例如:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
  </ItemGroup>

</Project>

视图组件

包含视图组件的项目应使用 Microsoft.NET.Sdk SDK。 若面向 .NET Core 3.x,则添加针对共享框架的 <FrameworkReference> 元素。 例如:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

若面向 .NET Standard(以支持 ASP.NET Core 3.x 之前的版本),则添加 Microsoft.AspNetCore.Mvc.ViewFeatures 的包引用。 Microsoft.AspNetCore.Mvc.ViewFeatures 包移到了共享框架,因此不再发布。 例如:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
  </ItemGroup>

</Project>

支持多个 ASP.NET Core 版本

创作支持多个 ASP.NET Core 变体的库需要多目标。 以下列情况为例:标记帮助器库必须支持以下 ASP.NET Core 变体:

  • 面向 .NET Framework 4.6.1 的 ASP.NET Core 2.1
  • 面向 .NET Core 2.x 的 ASP.NET Core 2.x
  • 面向 .NET Core 3.x 的 ASP.NET Core 3.x

以下项目文件通过 TargetFrameworks 属性支持这些变体:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

上面的项目文件将完成以下操作:

  • 为所有使用者添加 Markdig 包。
  • 为面向 .NET Framework 4.6.1 或更高版本或者 .NET Core 2.x 的使用者添加对 Microsoft.AspNetCore.Mvc.Razor 的引用。 由于向后兼容性,此包的版本 2.1.0 适用于 ASP.NET Core 2.2。
  • 为面向 .NET Core 3.x 的使用者引用共享框架。 共享框架中包括 Microsoft.AspNetCore.Mvc.Razor 包。

或者,可以面向 .NET Standard 2.0,而不面向 .NET Core 2.1 和 .NET Framework 4.6.1:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

对于上面的项目文件,有以下注意事项:

  • 由于库只包含标记帮助器,面向 ASP.NET Core 运行的特定平台(.NET Core 和 .NET Framework)更为简单。 其他兼容 .NET Standard 2.0 的目标框架(如 Unity、UWP 和 Xamarin)无法使用标记帮助器。
  • 在 .NET Framework 中使用 .NET Standard 2.0 存在一些问题,这些在 .NET Framework 4.7.2 中已得到解决。 通过面向 .NET Framework 4.6.1,可以改进使用 .NET Framework 4.6.1 到 4.7.1 的使用者的体验。

如果库需要调用平台特定的 API,则面向特定 .NET 实现,而不面向 .NET Standard。 有关详细信息,请参阅多目标

使用未变更的 API

想象一下,你要将中间件库从 .NET Core 2.2 升级到 3.1。 库正在使用的 ASP.NET Core 中间件 API 尚未从 ASP.NET Core 2.2 变更到 3.1。 若要使 .NET Core 3.1 继续支持此中间件库,请执行以下步骤:

  • 按照标准库指南操作。
  • 若共享框架中不存在相应的程序集,则添加针对每个 API 的 NuGet 包的包引用。

使用已变更的 API

想象一下,你要将库从 .NET Core 2.2 升级到 .NET Core 3.1。 库正在使用的 ASP.NET Core API 包含 ASP.NET Core 3.1 的中断性变更。 请考虑此库是否可以重写为不使用所有版本中已损坏的 API。

若可以重写此库,则进行重写,并通过包引用继续面向早期版本的目标框架(例如 .NET Standard 2.0 或 .NET Framework 4.6.1)。

若无法重写此库,则执行以下步骤:

  • 添加针对 .NET Core 3.1 的目标。
  • 添加针对共享框架的 <FrameworkReference> 元素。
  • 结合使用 #if 预处理器指令和对应的目标框架符号,以进行有条件的代码编译。

例如,自 ASP.NET Core 3.1 起,默认不可对 HTTP 请求和响应流进行同步读写。 默认情况下,ASP.NET Core 2.2 支持同步行为。 以一个中间件库为例,在该库中,发生 I/O 时应可进行同步读写。 此库应将用于启用同步功能的代码括在相应的预处理器指令中。 例如:

public async Task Invoke(HttpContext httpContext)
{
    if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal))
    {
        httpContext.Response.StatusCode = (int) HttpStatusCode.OK;
        httpContext.Response.ContentType = "application/json";
        httpContext.Response.ContentLength = _bufferSize;

#if !NETCOREAPP3_1 && !NETCOREAPP5_0
        var syncIOFeature = httpContext.Features.Get<IHttpBodyControlFeature>();
        if (syncIOFeature != null)
        {
            syncIOFeature.AllowSynchronousIO = true;
        }

        using (var sw = new StreamWriter(
            httpContext.Response.Body, _encoding, bufferSize: _bufferSize))
        {
            _json.Serialize(sw, new JsonMessage { message = "Hello, World!" });
        }
#else
        await JsonSerializer.SerializeAsync<JsonMessage>(
            httpContext.Response.Body, new JsonMessage { message = "Hello, World!" });
#endif
        return;
    }

    await _next(httpContext);
}

使用 3.1 引入的 API

假设你想要使用 ASP.NET Core 3.1 引入的 ASP.NET Core API。 请考虑下列问题:

  1. 此库在功能上是否需要此新 API?
  2. 库是否可以通过其他方式实现此功能?

若此库在功能上需要此 API,并且没有实现它的下层方法:

  • 仅面向 .NET Core 3.x。
  • 添加针对共享框架的 <FrameworkReference> 元素。

若此库可以通过其他方式实现此功能:

  • 将 .NET Core 3.x 添加为目标框架。
  • 添加针对共享框架的 <FrameworkReference> 元素。
  • 结合使用 #if 预处理器指令和对应的目标框架符号,以进行有条件的代码编译。

例如,以下标记帮助器使用 ASP.NET Core 3.1 引入的 IWebHostEnvironment 接口。 面向 .NET Core 3.1 的使用者执行 NETCOREAPP3_1 目标框架符号定义的代码路径。 对于 .NET Core 2.1 和 .NET Framework 4.6.1 使用者,标记帮助器的构造函数参数类型更改为 IHostingEnvironment。 此更改很有必要,因为 ASP.NET Core 3.1 将 IHostingEnvironment 标记为过时,并推荐将 IWebHostEnvironment 作为替代项。

[HtmlTargetElement("script", Attributes = "asp-inline")]
public class ScriptInliningTagHelper : TagHelper
{
    private readonly IFileProvider _wwwroot;

#if NETCOREAPP3_1
    public ScriptInliningTagHelper(IWebHostEnvironment env)
#else
    public ScriptInliningTagHelper(IHostingEnvironment env)
#endif
    {
        _wwwroot = env.WebRootFileProvider;
    }

    // code omitted for brevity
}

以下多目标项目文件支持此标记帮助器方案:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

使用共享框架已删除的 API

若要使用共享框架已删除的 ASP.NET Core 程序集,请添加相应的包引用。 若要查看 ASP.NET Core 3.1 的共享框架已删除的包列表,请参阅删除过时的包引用

例如,添加 Web API 客户端:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
  </ItemGroup>

</Project>

其他资源