使用 ASP.NET Core 中的 Razor 类库项目创建可重用 UICreate reusable UI using the Razor class library project in ASP.NET Core

本文内容

作者:Rick Anderson

Razor 视图、页面、控制器、页面模型、Razor 组件视图组件和数据模型可生成到 Razor 类库 (RCL) 中。RCL 可以打包并重复使用。应用程序可以包括 RCL,并重写其中包含的视图和页面。如果在 Web 应用和 RCL 中都能找到视图、分部视图或 Razor 页面,则 Web 应用中的 Razor 标记(.cshtml 文件)优先 。

查看或下载示例代码如何下载

创建一个包含 Razor UI 的类库Create a class library containing Razor UI

  • 在 Visual Studio 中,选择“创建新项目” 。
  • 选择“Razor 类库”>“下一步” 。
  • 命名库(例如,“RazorClassLib”)>“创建” 。为避免与已生成的视图库发生文件名冲突,请确保库名称不以 .Views 结尾。
  • 如果需要支持视图,请选择“支持页面和视图” 。默认情况下,仅支持 Razor Pages。选择“创建” 。

默认情况下,Razor 类库 (RCL) 模板默认为 Razor 组件开发。“支持页面和视图”选项支持页面和视图 。

从命令行中,运行 dotnet new razorclasslib例如:

  1. dotnet new razorclasslib -o RazorUIClassLib

默认情况下,Razor 类库 (RCL) 模板默认为 Razor 组件开发。传递 —support-pages-and-views 选项 (dotnet new razorclasslib —support-pages-and-views) 以提供页面和视图支持。

有关详细信息,请查看 dotnet new为避免与已生成的视图库发生文件名冲突,请确保库名称不以 .Views 结尾。

将 Razor 文件添加到 RCL。

ASP.NET Core 模板假定 RCL 内容位于 Areas 文件夹中。请参阅 RCL 页面布局,创建公开 ~/Pages 中内容(而非 ~/Areas/Pages 中内容)的 RCL。

引用 RCL 内容Reference RCL content

可以通过以下方式引用 RCL:

重写视图、分部视图和页面Override views, partial views, and pages

如果在 Web 应用和 RCL 中都能找到视图、分部视图或 Razor 页面,则 Web 应用中的 Razor 标记(.cshtml 文件)优先 。例如,将 WebApp1/Areas/MyFeature/Pages/Page1.cshtml 添加到 WebApp1,则 WebApp1 中的 Page1 会优先于 RCL 中的 Page1。

在示例下载中,将 WebApp1/Areas/MyFeature2 重命名为 WebApp1/Areas/MyFeature 来测试优先级 。

将 RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml 分部视图复制到 WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml 。更新标记以指示新的位置。生成并运行应用,验证使用部分的应用版本。

RCL 页面布局RCL Pages layout

若要将 RCL 内容作为 Web 应用 Pages 文件夹的一部分引用,请使用以下文件结构创建 RCL 项目:

  • RazorUIClassLib/Pages
  • RazorUIClassLib/Pages/Shared

假设 RazorUIClassLib/Pages/Shared 包含两个分部文件: Header.cshtml_ 和 Footer.cshtml可将 <partial> 标记添加到 __Layout.cshtml 文件:

  1. <body>
  2. <partial name="_Header">
  3. @RenderBody()
  4. <partial name="_Footer">
  5. </body>

创建具有静态资产的 RCLCreate an RCL with static assets

RCL 可能需要 RCL 或 RCL 的消耗应用可以引用的伴随静态资产。ASP.NET Core 允许创建 RCL,这些 RCL 包括可供消耗应用使用的静态资产。

若要将伴随资产作为 RCL 的一部分包括在内,请在类库中创建 wwwroot 文件夹,并在该文件夹中包括所有必需的文件。

打包 RCL 时,wwwroot 文件夹中的所有伴随资产都会自动包括在包中。

排除静态资产Exclude static assets

若要排除静态资产,请将所需的排除路径添加到项目文件中的 $(DefaultItemExcludes) 属性组。使用分号 (;) 分隔条目。

在以下示例中,wwwroot 文件夹中的 lib.css 样式表不被视为静态资产,并且不包括在已发布的 RCL 中:

  1. <PropertyGroup>
  2. <DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
  3. </PropertyGroup>

TypeScript 集成Typescript integration

若要在 RCL 中包括 TypeScript 文件,请执行以下操作:

  • 将 TypeScript 文件 ( .ts) 置于 wwwroot 文件夹之外。例如,将文件置于 Client 文件夹中。

  • wwwroot 文件夹配置 TypeScript 生成输出。在项目文件的 PropertyGroup 内设置 TypescriptOutDir 属性:

  1. <TypescriptOutDir>wwwroot</TypescriptOutDir>
  • 通过在项目文件的 PropertyGroup 内添加以下目标,将 TypeScript 目标作为 ResolveCurrentProjectStaticWebAssets 目标的依赖项包括在内:
  1. <ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
  2. CompileTypeScript;
  3. $(ResolveCurrentProjectStaticWebAssetsInputs)
  4. </ResolveCurrentProjectStaticWebAssetsInputsDependsOn>

使用引用的 RCL 中的内容Consume content from a referenced RCL

RCL 的 wwwroot 文件夹中包括的文件使用前缀 content/{LIBRARY NAME}/ 向 RCL 或消耗应用公开。例如,名为 _Razor.Class.Lib 的库会生成指向 _content/Razor.Class.Lib/ 处的静态内容的路径。生成 NuGet 包且程序集名称与包 ID 不同时,请将包 ID 用于 {LIBRARY NAME}

消耗应用使用 <script><style><img> 和其他 HTML 标记引用库提供的静态资产。消耗应用必须在 Startup.Configure 中启用静态文件支持

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3. ...
  4. app.UseStaticFiles();
  5. ...
  6. }

从生成输出 (dotnet run) 运行消耗应用时,默认在开发环境中启用静态 Web 资产。从生成输出运行时,若要在其他环境中支持资产,请在 Program.cs 中的主机生成器上调用 UseStaticWebAssets

  1. using Microsoft.AspNetCore.Hosting;
  2. using Microsoft.Extensions.Hosting;
  3. public class Program
  4. {
  5. public static void Main(string[] args)
  6. {
  7. CreateHostBuilder(args).Build().Run();
  8. }
  9. public static IHostBuilder CreateHostBuilder(string[] args) =>
  10. Host.CreateDefaultBuilder(args)
  11. .ConfigureWebHostDefaults(webBuilder =>
  12. {
  13. webBuilder.UseStaticWebAssets();
  14. webBuilder.UseStartup<Startup>();
  15. });
  16. }

从已发布输出 (dotnet publish) 运行应用时,无需调用 UseStaticWebAssets

多项目开发流程Multi-project development flow

消耗应用运行时:

  • RCL 中的资产停留在其原始文件夹中。资产不会移至消耗应用。
  • 重新生成 RCL 后,RCL 的 wwwroot 文件夹中的所有更改都会反映在消耗应用中,而无需重新生成消耗应用。

生成 RCL 时,还会生成描述静态 Web 资产位置的清单。消耗应用在运行时读取清单,以使用引用项目和包中的资产。将新资产添加到 RCL 后,必须先重新生成 RCL 以更新其清单,然后消耗应用才能访问新资产。

发布Publish

发布应用后,来自所有引用项目和包的伴随资产都会复制到已发布应用的 wwwroot 文件夹中的 _content/{LIBRARY NAME}/ 下。

Razor 视图、页面、控制器、页面模型、Razor 组件视图组件和数据模型可生成到 Razor 类库 (RCL) 中。RCL 可以打包并重复使用。应用程序可以包括 RCL,并重写其中包含的视图和页面。如果在 Web 应用和 RCL 中都能找到视图、分部视图或 Razor 页面,则 Web 应用中的 Razor 标记(.cshtml 文件)优先 。

查看或下载示例代码如何下载

创建一个包含 Razor UI 的类库Create a class library containing Razor UI

  • 从 Visual Studio“文件” 菜单中选择“新建” >“项目” 。
  • 选择“ASP.NET Core Web 应用程序” 。
  • 命名库(例如,“RazorClassLib”)>“确定” 。为避免与已生成的视图库发生文件名冲突,请确保库名称不以 .Views 结尾。
  • 验证是否已选择 ASP.NET Core 2.1 或更高版本 。
  • 选择“Razor 类库”>“确定” 。

RCL 具有以下项目文件:

  1. <Project Sdk="Microsoft.NET.Sdk.Razor">
  2. <PropertyGroup>
  3. <TargetFramework>netstandard2.0</TargetFramework>
  4. </PropertyGroup>
  5. <ItemGroup>
  6. <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
  7. </ItemGroup>
  8. </Project>

从命令行中,运行 dotnet new razorclasslib例如:

  1. dotnet new razorclasslib -o RazorUIClassLib

有关详细信息,请查看 dotnet new为避免与已生成的视图库发生文件名冲突,请确保库名称不以 .Views 结尾。

将 Razor 文件添加到 RCL。

ASP.NET Core 模板假定 RCL 内容位于 Areas 文件夹中。请参阅 RCL 页面布局,创建公开 ~/Pages 中内容(而非 ~/Areas/Pages 中内容)的 RCL。

引用 RCL 内容Reference RCL content

可以通过以下方式引用 RCL:

演练:创建 RCL 项目并通过 Razor Pages 项目使用Walkthrough: Create an RCL project and use from a Razor Pages project

可以下载并测试完整项目,无需创建项目。示例下载包含附加代码和链接,以方便测试项目。可以在此 GitHub 问题中留下反馈,评论下载示例和分步说明的对比。

测试下载应用Test the download app

如果尚未下载已完成的应用,并更愿意创建演练项目,请跳转至下一节

在 Visual Studio 中打开 .sln 文件 。运行应用。

在 cli 目录中的命令提示符下生成 RCL 和 Web 应用 。

  1. dotnet build

移动至 WebApp1 目录,并运行应用 :

  1. dotnet run

“测试 Test WebApp1”中的说明进行操作

创建 RCLCreate an RCL

本部分会创建 RCL。将 Razor 文件添加到 RCL。

创建 RCL 项目:

  • 从 Visual Studio“文件” 菜单中选择“新建” >“项目” 。
  • 选择“ASP.NET Core Web 应用程序” 。
  • 将应用命名为“RazorUIClassLib”>“确定” 。
  • 验证是否已选择 ASP.NET Core 2.1 或更高版本 。
  • 选择“Razor 类库”>“确定” 。
  • 添加一个名为 RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml 的 Razor 分部视图文件 。

从命令行运行以下命令:

  1. dotnet new razorclasslib -o RazorUIClassLib
  2. dotnet new page -n _Message -np -o RazorUIClassLib/Areas/MyFeature/Pages/Shared
  3. dotnet new viewstart -o RazorUIClassLib/Areas/MyFeature/Pages

前面的命令:

  • 创建 RazorUIClassLib RCL。
  • 创建 Razor _Message 页面,并将其添加至 RCL。-np 参数创建不含 PageModel 的页面。
  • 创建 _ViewStart.cshtml 文件并将其添加到 RCL。

使用 Razor Pages 项目的布局需要 _ViewStart.cshtml 文件(在下一部分中添加)。

将 Razor 文件和文件夹添加到项目Add Razor files and folders to the project

  • 使用以下代码替换 RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml 中的标记 :
  1. <h3>_Message.cshtml partial view.</h3>
  2. <p>RazorUIClassLib\Areas\MyFeature\Pages\Shared\_Message.cshtml</p>
  • 使用以下代码替换 RazorUIClassLib/Areas/MyFeature/Pages/Page1.cshtml 中的标记 :
  1. @page
  2. @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
  3. <h2>Hello from a Razor UI class library!</h2>
  4. <p> From RazorUIClassLib\Areas\MyFeature\Pages\Page1.cshtml</p>
  5. <partial name="_Message" />

使用分步视图 (<partial name="_Message" />) 需要 @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers。可以添加一个 _ViewImports.cshtml 文件,无需包含 @addTagHelper 指令 。例如:

  1. dotnet new viewimports -o RazorUIClassLib/Areas/MyFeature/Pages

有关 _ViewImports.cshtml 的详细信息,请参阅导入共享指令

  • 生成类库以验证是否不存在编译器错误:
  1. dotnet build RazorUIClassLib

生成输出内容包含 RazorUIClassLib.dll 和 RazorUIClassLib.Views.dll 。RazorUIClassLib.Views.dll 包含已编译的 Razor 内容 。

从 Razor 页面项目使用 Razor UI 库Use the Razor UI library from a Razor Pages project

创建 Razor 页面 Web 应用:

  • 在“解决方案资源管理器”中,右键单击解决方案 >“添加”>“新建项目” 。

  • 选择“ASP.NET Core Web 应用程序” 。

  • 将应用命名为 WebApp1 。

  • 验证是否已选择 ASP.NET Core 2.1 或更高版本 。

  • 选择“Web 应用”>“确定” 。

  • 在解决方案资源管理器中,右键单击“WebApp1”,然后选择“设为启动项目” 。

  • 在“解决方案资源管理器”中,右键单击“WebApp1”,然后选择“生成依赖项”>“项目依赖项” 。

  • 将 RazorUIClassLib 勾选为 WebApp1 的依赖项 。

  • 在“解决方案资源管理器”中,右键单击“WebApp1”,然后选择“添加”>“引用” 。

  • 在“引用管理器”对话框中勾选“RazorUIClassLib”>“确定” 。

运行应用。

创建 Razor Pages Web 应用和包含 Razor Pages 应用及 RCL 的解决方案文件:

  1. dotnet new webapp -o WebApp1
  2. dotnet new sln
  3. dotnet sln add WebApp1
  4. dotnet sln add RazorUIClassLib
  5. dotnet add WebApp1 reference RazorUIClassLib

生成并运行 Web 应用:

  1. cd WebApp1
  2. dotnet run

测试 WebApp1Test WebApp1

浏览到 /MyFeature/Page1 以验证是否正在使用 Razor UI 类库。

重写视图、分部视图和页面Override views, partial views, and pages

如果在 Web 应用和 RCL 中都能找到视图、分部视图或 Razor 页面,则 Web 应用中的 Razor 标记(.cshtml 文件)优先 。例如,将 WebApp1/Areas/MyFeature/Pages/Page1.cshtml 添加到 WebApp1,则 WebApp1 中的 Page1 会优先于 RCL 中的 Page1。

在示例下载中,将 WebApp1/Areas/MyFeature2 重命名为 WebApp1/Areas/MyFeature 来测试优先级 。

将 RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml 分部视图复制到 WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml 。更新标记以指示新的位置。生成并运行应用,验证使用部分的应用版本。

RCL 页面布局RCL Pages layout

若要将 RCL 内容作为 Web 应用 Pages 文件夹的一部分引用,请使用以下文件结构创建 RCL 项目:

  • RazorUIClassLib/Pages
  • RazorUIClassLib/Pages/Shared

假设 RazorUIClassLib/Pages/Shared 包含两个分部文件: Header.cshtml_ 和 Footer.cshtml可将 <partial> 标记添加到 __Layout.cshtml 文件:

  1. <body>
  2. <partial name="_Header">
  3. @RenderBody()
  4. <partial name="_Footer">
  5. </body>

其他资源Additional resources