在类库中使用 ASP.NET 核心 API

作者:Scott Addie

本文档提供有关在类库中使用 ASP.NET 核心 API 的指导。 有关所有其他库指南,请参阅 开源库指南

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

ASP.NET Core 遵循 .NET Core 支持策略。 确定库中要支持哪些 ASP.NET 核心版本时,请参阅支持策略。 图书馆应该:

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

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

使用 ASP.NET Core 共享框架

随着 .NET Core 3.0 的发布,许多 ASP.NET 核心程序集不再作为包发布到 NuGet。 相反,程序集包含在 Microsoft.AspNetCore.App 共享框架中,该框架随 .NET Core SDK 和运行时安装程序一起安装。 若要查看不再发布的包列表,请参阅删除过时的包引用

从 .NET Core 3.0 起,使用 Microsoft.NET.Sdk.Web MSBuild SDK 的项目会隐式引用共享框架。 使用 Microsoft.NET.SdkMicrosoft.NET.Sdk.Razor SDK 的项目必须引用 ASP.NET Core 才能在共享框架中使用 ASP.NET 核心 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.Sdk。Razor SDK

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

若要支持服务器端应用和客户端应用通过单个库使用 Razor 组件,请按照以下说明在编辑器中使用。

使用 Razor 类库 项目模板。

注意

不要选中“支持页面和视图”复选框。 选中复选框会导致类库仅支持服务器端应用。

从项目模板生成的库:

  • 基于已安装的 SDK,定位当前的 .NET 框架。
  • 通过将 browser 作为受支持的平台包含在 SupportedPlatform MSBuild 项中,启用有关平台依赖项的浏览器兼容性检查。
  • Microsoft.AspNetCore.Components.Web添加 NuGet 包引用。

RazorClassLibrary-CSharp.csproj(参考源)

注意

指向 .NET 引用源的文档链接通常会加载存储库的默认分支,该分支代表正在进行的 .NET 下一版本的开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅 如何选择 ASP.NET 核心源代码的版本标记(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 核心版本的指南,请参阅 支持多个 ASP.NET 核心版本

Razor 视图或 Razor 页面

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

如果项目面向 .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 核心版本

需要进行多目标设置以便于编写支持多个 ASP.NET Core 变体的程序库。 假设标记帮助程序库必须支持以下 ASP.NET 核心变体:

  • 面向 .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)不能使用标记帮助程序。
  • 在 .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 核心中间件 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 目标框架符号定义的代码路径。 标记帮助程序的构造函数参数类型更改为 IHostingEnvironment,适用于 .NET Core 2.1 和 .NET Framework 4.6.1 的使用者。 此更改是必需的,因为 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>

其他资源