使用类库中的 ASP.NET Core API
作者:Scott Addie
此文档提供了关于如何使用类库中的 ASP.NET Core API 的指南。 若要查看所有其他的库指南,请参阅开放源代码库指南。
ASP.NET Core 遵从 .NET Core 支持策略。 确定库要支持哪些 ASP.NET Core 版本时,请参阅支持策略。 库应符合以下条件:
- 努力支持列为“长期支持”(LTS) 类别的所有 ASP.NET Core 版本。
- 无需支持列为“生命周期结束”(EOL) 类别的 ASP.NET Core 版本。
由于 ASP.NET Core 预览版已推出,因此已在 aspnet/Announcements GitHub 存储库中发布中断性变更。 开发框架功能时,可执行库兼容性测试。
随着 .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.Sdk
或 Microsoft.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 支持为服务器端和客户端应用创建 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
。
很少有仅支持服务器端应用的类库。 如果类库仅需要特定于服务器端的功能(如访问 CircuitHandler 或 Microsoft.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 版本的多目标。 若要查看关于支持多个 ASP.NET Core 版本的指南,请参阅支持多个 ASP.NET Core 版本。
包括 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 变体:
- 面向 .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。 有关详细信息,请参阅多目标。
想象一下,你要将中间件库从 .NET Core 2.2 升级到 3.1。 库正在使用的 ASP.NET Core 中间件 API 尚未从 ASP.NET Core 2.2 变更到 3.1。 若要使 .NET Core 3.1 继续支持此中间件库,请执行以下步骤:
- 按照标准库指南操作。
- 若共享框架中不存在相应的程序集,则添加针对每个 API 的 NuGet 包的包引用。
想象一下,你要将库从 .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);
}
假设你想要使用 ASP.NET Core 3.1 引入的 ASP.NET Core API。 请考虑下列问题:
- 此库在功能上是否需要此新 API?
- 库是否可以通过其他方式实现此功能?
若此库在功能上需要此 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>
若要使用共享框架已删除的 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>