ASP.NET Core の Razor クラス ライブラリ プロジェクトを使用した再利用可能 UI の作成
作成者: Rick Anderson
Razor ビュー、ページ、コントローラー、ページ モデル、Razor コンポーネント、ビュー コンポーネント、データ モデルは、Razor クラス ライブラリ (RCL) に組み込むことが可能です。 RCL はパッケージ化し、再利用できます。 アプリケーションには RCL を含めることができます。また、それに含まれるビューやページをオーバーライドできます。 Web アプリと RCL の両方にビュー、部分ビュー、Razor ページがあるとき、Web アプリの Razor マークアップ ( .cshtml
ファイル) が優先されます。
npm と webpack を RCL のビルド プロセスに統合する方法については、「Razor クラス ライブラリ用のクライアント Web アセットのビルド」を参照してください。
Razor UI を含むクラス ライブラリの作成
- Visual Studio から [新しいプロジェクトの作成] を選択します。
- [Razor クラス ライブラリ]>[次へ] の順に選択します。
- ライブラリに名前を付け ("RazorClassLib" など)、>[作成] を選択します。 生成されたビュー ライブラリとファイル名の競合を避けるため、ライブラリ名の末尾が
.Views
ではないことを確認します。 - ライブラリにページやビューを含める必要がある場合は、[サポート ページとビュー] を選択します。 既定では、Razor コンポーネントのみがサポートされています。 [作成] を選択します
Razor クラス ライブラリ テンプレートは Razor コンポーネント開発の既定値です。 [ページとビューのサポート] オプションによって、ページとビューがサポートされます。 Blazor での RCL サポートについて詳しくは、「ASP.NET Core Razor コンポーネントを Razor クラス ライブラリ (RCL) から使用する」をご覧ください。
RCL に Razor ファイルを追加します。
ASP.NET Core テンプレートでは、RCL コンテンツが Areas
フォルダーにあると見なされます。 ~/Areas/Pages
ではなく ~/Pages
でコンテンツを公開する RCL を作成する場合は、後述の「RCL ページのレイアウト」を参照してください。
RCL コンテンツを参照する
RCL は次によって参照できます。
- NuGet パッケージ。 「Creating NuGet packages」 (NuGet パッケージの作成)、「dotnet add package」、「Create and publish a NuGet package」 (NuGet パッケージの作成と公開) を参照してください。
{ProjectName}.csproj
: 「dotnet-add reference」を参照してください。
ビュー、部分ビュー、ページのオーバーライド
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 で Razor Pages を使用する場合は、ホスティング アプリで Razor Pages サービスとエンドポイントを有効にします。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
RCL ページのレイアウト
RCL コンテンツを Web アプリの Pages
フォルダーの一部であるかのように参照するには、次のファイル構造で RCL プロジェクトを作成します。
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
RazorUIClassLib/Pages/Shared
に 2 つの部分ファイル (_Header.cshtml
と _Footer.cshtml
) が含まれているとします。 これらの <partial>
タグを _Layout.cshtml
ファイルに追加できます。
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
_ViewStart.cshtml
ファイルを、RCL プロジェクトの Pages
フォルダーに追加して、ホスト Web アプリの _Layout.cshtml
ファイルを使用します。
@{
Layout = "_Layout";
}
静的アセットを含む RCL を作成する
RCL では、RCL または RCL の使用アプリで参照できる静的なコンパニオン アセットが必要になる場合があります。 ASP.NET Core では、使用アプリで利用できる静的アセットを含む RCL の作成が可能です。
コンパニオン アセットを RCL の一部として含めるには、クラス ライブラリに wwwroot
フォルダーを作成し、必要なファイルをすべてそのフォルダーに含めます。
RCL をパックすると、wwwroot
フォルダー内のすべてのコンパニオン アセットがパッケージに自動的に含まれます。
Nuget.exe バージョン nuget pack
ではなく、dotnet pack
コマンドを使用します。
クライアント Web 資産をビルド プロセスに追加する
クライアント Web 資産をビルド パイプラインに統合することは簡単ではありません。 詳細については、「Build client web assets for your Razor Class Library (Razor クラス ライブラリのクライアント Web 資産を構築する)」を参照してください。
静的アセットを除外する
静的アセットを除外するには、目的の除外パスをプロジェクトファイル内の $(DefaultItemExcludes)
プロパティ グループに追加します。 各エントリは、セミコロン (;
) で区切ります。
次の例では、wwwroot
フォルダー内の lib.css
スタイルシートが静的アセットとは見なされず、公開された RCL には含まれていません。
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript の統合
TypeScript ファイルを RCL に含めるには、次の操作を行います。
プロジェクトで
Microsoft.TypeScript.MSBuild
NuGet パッケージを参照します。Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
TypeScript ファイル (
.ts
) をwwwroot
フォルダーの外側に配置します。 たとえば、ファイルをClient
フォルダーに配置します。wwwroot
フォルダーの TypeScript ビルド出力を構成します。 プロジェクト ファイルのPropertyGroup
の内側にTypescriptOutDir
プロパティを設定します。<TypescriptOutDir>wwwroot</TypescriptOutDir>
プロジェクト ファイルの
PropertyGroup
の内側に次のターゲットを追加して、TypeScript ターゲットをPrepareForBuildDependsOn
ターゲットの依存関係として含めます。<PrepareForBuildDependsOn> CompileTypeScript; GetTypeScriptOutputForPublishing;$(PrepareForBuildDependsOn) </PrepareForBuildDependsOn>
参照されている RCL からコンテンツを使用する
RCL の wwwroot
フォルダーに含まれるファイルは、_content/{PACKAGE ID}/
プレフィックスに基づいて RCL または使用アプリのいずれかに公開されます。 たとえば、アセンブリ名が Razor.Class.Lib
で、そのプロジェクト ファイルに <PackageId>
が指定されていないライブラリの場合、_content/Razor.Class.Lib/
の静的コンテンツへのパスが生成されます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の<PackageId>
) と異なる場合は、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
使用アプリは、ライブラリによって提供される静的アセットを <script>
、<style>
、<img>
、およびその他の HTML タグ付きで参照します。 使用アプリで、次のように静的ファイルのサポートが有効になっている必要があります。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
使用アプリをビルド出力から実行 (dotnet run
) すると、開発環境で、静的な Web アセットが既定で有効になります。 ビルド出力から実行するときに他の環境のアセットをサポートするには、Program.cs
のホスト ビルダーで UseStaticWebAssets を呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseWebRoot("wwwroot");
builder.WebHost.UseStaticWebAssets();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
発行された出力からアプリを実行する (dotnet publish
) 場合、UseStaticWebAssets
の呼び出しは必要ありません。
複数プロジェクトの開発フロー
使用アプリの実行時は、次のようになります。
- RCL のアセットは元のフォルダー内に保持されます。 これらのアセットは、使用アプリに移行されません。
- RCL の
wwwroot
フォルダー内の変更は、使用アプリをリビルドしなくても、RCL がリビルドされた後で、使用アプリに反映されます。
RCL がビルドされると、静的な Web アセットの場所を記述するマニフェストが生成されます。 使用アプリは、実行時にそのマニフェストを読み取って、参照されているプロジェクトおよびパッケージのアセットを使用します。 RCL に新しいアセットが追加された場合は、使用アプリがその新しいアセットにアクセスする前に、RCL をリビルドしてそのマニフェストを更新する必要があります。
公開
アプリが公開されると、参照されているすべてのプロジェクトおよびパッケージのコンパニオン アセットが、_content/{PACKAGE ID}/
の下の公開済みアプリの wwwroot
フォルダーにコピーされます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の <PackageId>
) と同じではない場合は、発行されたアセットの wwwroot
フォルダーを調べるときに、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
その他のリソース
Razor ビュー、ページ、コントローラー、ページ モデル、Razor コンポーネント、ビュー コンポーネント、データ モデルは、Razor クラス ライブラリ (RCL) に組み込むことが可能です。 RCL はパッケージ化し、再利用できます。 アプリケーションには RCL を含めることができます。また、それに含まれるビューやページをオーバーライドできます。 Web アプリと RCL の両方にビュー、部分ビュー、Razor ページがあるとき、Web アプリの Razor マークアップ ( .cshtml
ファイル) が優先されます。
npm と webpack を Razor クラス ライブラリのビルド プロセスに統合する方法については、「Razor クラス ライブラリのクライアント Web アセットをビルドする」を参照してください。
Razor UI を含むクラス ライブラリの作成
- Visual Studio から [新しいプロジェクトの作成] を選択します。
- [Razor クラス ライブラリ]>[次へ] の順に選択します。
- ライブラリに名前を付け ("RazorClassLib" など)、>[作成] を選択します。 生成されたビュー ライブラリとファイル名の競合を避けるため、ライブラリ名の末尾が
.Views
ではないことを確認します。 - ビューをサポートする必要がある場合は、 [ページとビューのサポート] を選択します。 既定では、Razor ページのみがサポートされています。 [作成] を選択します。
Razor クラス ライブラリ (RCL) テンプレートは Razor コンポーネント開発での既定です。 [ページとビューのサポート] オプションによって、ページとビューがサポートされます。
RCL に Razor ファイルを追加します。
ASP.NET Core テンプレートでは、RCL コンテンツが Areas
フォルダーにあると見なされます。 ~/Areas/Pages
ではなく ~/Pages
でコンテンツを公開する RCL を作成する場合は、後述の「RCL ページのレイアウト」を参照してください。
RCL コンテンツを参照する
RCL は次によって参照できます。
- NuGet パッケージ。 「Creating NuGet packages」 (NuGet パッケージの作成)、「dotnet add package」、「Create and publish a NuGet package」 (NuGet パッケージの作成と公開) を参照してください。
{ProjectName}.csproj
: 「dotnet-add reference」を参照してください。
ビュー、部分ビュー、ページのオーバーライド
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 で Razor Pages を使用する場合は、ホスティング アプリで Razor Pages サービスとエンドポイントを有効にします。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
RCL ページのレイアウト
RCL コンテンツを Web アプリの Pages
フォルダーの一部であるかのように参照するには、次のファイル構造で RCL プロジェクトを作成します。
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
RazorUIClassLib/Pages/Shared
に 2 つの部分ファイル (_Header.cshtml
と _Footer.cshtml
) が含まれているとします。 これらの <partial>
タグを _Layout.cshtml
ファイルに追加できます。
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
_ViewStart.cshtml
ファイルを、RCL プロジェクトの Pages
フォルダーに追加して、ホスト Web アプリの _Layout.cshtml
ファイルを使用します。
@{
Layout = "_Layout";
}
静的アセットを含む RCL を作成する
RCL では、RCL または RCL の使用アプリで参照できる静的なコンパニオン アセットが必要になる場合があります。 ASP.NET Core では、使用アプリで利用できる静的アセットを含む RCL の作成が可能です。
コンパニオン アセットを RCL の一部として含めるには、クラス ライブラリに wwwroot
フォルダーを作成し、必要なファイルをすべてそのフォルダーに含めます。
RCL をパックすると、wwwroot
フォルダー内のすべてのコンパニオン アセットがパッケージに自動的に含まれます。
Nuget.exe バージョン nuget pack
ではなく、dotnet pack
コマンドを使用します。
静的アセットを除外する
静的アセットを除外するには、目的の除外パスをプロジェクトファイル内の $(DefaultItemExcludes)
プロパティ グループに追加します。 各エントリは、セミコロン (;
) で区切ります。
次の例では、wwwroot
フォルダー内の lib.css
スタイルシートが静的アセットとは見なされず、公開された RCL には含まれていません。
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript の統合
TypeScript ファイルを RCL に含めるには、次の操作を行います。
プロジェクトで
Microsoft.TypeScript.MSBuild
NuGet パッケージを参照します。Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
TypeScript ファイル (
.ts
) をwwwroot
フォルダーの外側に配置します。 たとえば、ファイルをClient
フォルダーに配置します。wwwroot
フォルダーの TypeScript ビルド出力を構成します。 プロジェクト ファイルのPropertyGroup
の内側にTypescriptOutDir
プロパティを設定します。<TypescriptOutDir>wwwroot</TypescriptOutDir>
プロジェクト ファイルの
PropertyGroup
の内側に次のターゲットを追加して、TypeScript ターゲットをPrepareForBuildDependsOn
ターゲットの依存関係として含めます。<PrepareForBuildDependsOn> CompileTypeScript; GetTypeScriptOutputForPublishing;$(PrepareForBuildDependsOn) </PrepareForBuildDependsOn>
参照されている RCL からコンテンツを使用する
RCL の wwwroot
フォルダーに含まれるファイルは、_content/{PACKAGE ID}/
プレフィックスに基づいて RCL または使用アプリのいずれかに公開されます。 たとえば、アセンブリ名が Razor.Class.Lib
で、そのプロジェクト ファイルに <PackageId>
が指定されていないライブラリの場合、_content/Razor.Class.Lib/
の静的コンテンツへのパスが生成されます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の<PackageId>
) と異なる場合は、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
使用アプリは、ライブラリによって提供される静的アセットを <script>
、<style>
、<img>
、およびその他の HTML タグ付きで参照します。 使用アプリで、次のように静的ファイルのサポートが有効になっている必要があります。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
使用アプリをビルド出力から実行 (dotnet run
) すると、開発環境で、静的な Web アセットが既定で有効になります。 ビルド出力から実行するときに他の環境のアセットをサポートするには、Program.cs
のホスト ビルダーで UseStaticWebAssets を呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseWebRoot("wwwroot").UseStaticWebAssets();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
注: .NET 6 では builder.WebHost.UseWebRoot("wwwroot").UseStaticWebAssets
の呼び出しのみが必要です。 詳細については、こちらの GitHub の問題のページを参照してください。
発行された出力からアプリを実行する (dotnet publish
) 場合、UseStaticWebAssets
の呼び出しは必要ありません。
複数プロジェクトの開発フロー
使用アプリの実行時は、次のようになります。
- RCL のアセットは元のフォルダー内に保持されます。 これらのアセットは、使用アプリに移行されません。
- RCL の
wwwroot
フォルダー内の変更は、使用アプリをリビルドしなくても、RCL がリビルドされた後で、使用アプリに反映されます。
RCL がビルドされると、静的な Web アセットの場所を記述するマニフェストが生成されます。 使用アプリは、実行時にそのマニフェストを読み取って、参照されているプロジェクトおよびパッケージのアセットを使用します。 RCL に新しいアセットが追加された場合は、使用アプリがその新しいアセットにアクセスする前に、RCL をリビルドしてそのマニフェストを更新する必要があります。
公開
アプリが公開されると、参照されているすべてのプロジェクトおよびパッケージのコンパニオン アセットが、_content/{PACKAGE ID}/
の下の公開済みアプリの wwwroot
フォルダーにコピーされます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の <PackageId>
) と同じではない場合は、発行されたアセットの wwwroot
フォルダーを調べるときに、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
その他のリソース
Razor ビュー、ページ、コントローラー、ページ モデル、Razor コンポーネント、ビュー コンポーネント、データ モデルは、Razor クラス ライブラリ (RCL) に組み込むことが可能です。 RCL はパッケージ化し、再利用できます。 アプリケーションには RCL を含めることができます。また、それに含まれるビューやページをオーバーライドできます。 Web アプリと RCL の両方にビュー、部分ビュー、Razor ページがあるとき、Web アプリの Razor マークアップ ( .cshtml
ファイル) が優先されます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
Razor UI を含むクラス ライブラリの作成
- Visual Studio から [新しいプロジェクトの作成] を選択します。
- [Razor クラス ライブラリ]>[次へ] の順に選択します。
- ライブラリに名前を付け ("RazorClassLib" など)、>[作成]>[次へ] の順に選択します。 生成されたビュー ライブラリとファイル名の競合を避けるため、ライブラリ名の末尾が
.Views
ではないことを確認します。 - [ターゲット フレームワーク] を選択します。 ビューをサポートするための [☑ ページとビューのサポート] をチェックします。 既定では、Razor コンポーネントのみがサポートされています。 [作成] を選択します。
Razor クラス ライブラリ (RCL) テンプレートは Razor コンポーネント開発での既定です。 [ページとビューのサポート] オプションによって、ページとビューがサポートされます。
RCL に Razor ファイルを追加します。
ASP.NET Core テンプレートでは、RCL コンテンツが Areas
フォルダーにあるものとしています。 ~/Areas/Pages
ではなく ~/Pages
でコンテンツを公開する RCL を作成する場合は、「RCL ページのレイアウト」を参照してください。
RCL コンテンツを参照する
RCL は次によって参照できます。
- NuGet パッケージ。 「Creating NuGet packages」 (NuGet パッケージの作成)、「dotnet add package」、「Create and publish a NuGet package」 (NuGet パッケージの作成と公開) を参照してください。
{ProjectName}.csproj
: 「dotnet-add reference」を参照してください。
ビュー、部分ビュー、ページのオーバーライド
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 コンテンツを Web アプリの Pages
フォルダーの一部であるかのように参照するには、次のファイル構造で RCL プロジェクトを作成します。
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
RazorUIClassLib/Pages/Shared
に 2 つの部分ファイル (_Header.cshtml
と _Footer.cshtml
) が含まれているとします。 これらの <partial>
タグを _Layout.cshtml
ファイルに追加できます。
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
_ViewStart.cshtml
ファイルを、RCL プロジェクトの Pages
フォルダーに追加して、ホスト Web アプリの _Layout.cshtml
ファイルを使用します。
@{
Layout = "_Layout";
}
静的アセットを含む RCL を作成する
RCL では、RCL または RCL の使用アプリで参照できる静的なコンパニオン アセットが必要になる場合があります。 ASP.NET Core では、使用アプリで利用できる静的アセットを含む RCL の作成が可能です。
コンパニオン アセットを RCL の一部として含めるには、クラス ライブラリに wwwroot
フォルダーを作成し、必要なファイルをすべてそのフォルダーに含めます。
RCL をパックすると、wwwroot
フォルダー内のすべてのコンパニオン アセットがパッケージに自動的に含まれます。
Nuget.exe バージョン nuget pack
ではなく、dotnet pack
コマンドを使用します。
静的アセットを除外する
静的アセットを除外するには、目的の除外パスをプロジェクトファイル内の $(DefaultItemExcludes)
プロパティ グループに追加します。 各エントリは、セミコロン (;
) で区切ります。
次の例では、wwwroot
フォルダー内の lib.css
スタイルシートが静的アセットとは見なされず、公開された RCL には含まれていません。
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript の統合
TypeScript ファイルを RCL に含めるには、次の操作を行います。
プロジェクトで
Microsoft.TypeScript.MSBuild
NuGet パッケージを参照します。Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
TypeScript ファイル (
.ts
) をwwwroot
フォルダーの外側に配置します。 たとえば、ファイルをClient
フォルダーに配置します。wwwroot
フォルダーの TypeScript ビルド出力を構成します。 プロジェクト ファイルのPropertyGroup
の内側にTypescriptOutDir
プロパティを設定します。<TypescriptOutDir>wwwroot</TypescriptOutDir>
プロジェクト ファイルの
PropertyGroup
の内側に次のターゲットを追加して、TypeScript ターゲットをResolveCurrentProjectStaticWebAssets
ターゲットの依存関係として含めます。<ResolveCurrentProjectStaticWebAssetsInputsDependsOn> CompileTypeScript; $(ResolveCurrentProjectStaticWebAssetsInputs) </ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
参照されている RCL からコンテンツを使用する
RCL の wwwroot
フォルダーに含まれるファイルは、_content/{PACKAGE ID}/
プレフィックスに基づいて RCL または使用アプリのいずれかに公開されます。 たとえば、アセンブリ名が Razor.Class.Lib
で、そのプロジェクト ファイルに <PackageId>
が指定されていないライブラリの場合、_content/Razor.Class.Lib/
の静的コンテンツへのパスが生成されます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の<PackageId>
) と異なる場合は、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
使用アプリは、ライブラリによって提供される静的アセットを <script>
、<style>
、<img>
、およびその他の HTML タグ付きで参照します。 使用アプリの Startup.Configure
で 静的ファイルのサポートが有効になっている必要があります。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseStaticFiles();
...
}
使用アプリをビルド出力から実行 (dotnet run
) すると、開発環境で、静的な Web アセットが既定で有効になります。 ビルド出力から実行するときに他の環境のアセットをサポートするには、Program.cs
のホスト ビルダーで UseStaticWebAssets
を呼び出します。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
});
}
発行された出力からアプリを実行する (dotnet publish
) 場合、UseStaticWebAssets
の呼び出しは必要ありません。
複数プロジェクトの開発フロー
使用アプリの実行時は、次のようになります。
- RCL のアセットは元のフォルダー内に保持されます。 これらのアセットは、使用アプリに移行されません。
- RCL の
wwwroot
フォルダー内の変更は、使用アプリをリビルドしなくても、RCL がリビルドされた後で、使用アプリに反映されます。
RCL がビルドされると、静的な Web アセットの場所を記述するマニフェストが生成されます。 使用アプリは、実行時にそのマニフェストを読み取って、参照されているプロジェクトおよびパッケージのアセットを使用します。 RCL に新しいアセットが追加された場合は、使用アプリがその新しいアセットにアクセスする前に、RCL をリビルドしてそのマニフェストを更新する必要があります。
公開
アプリが公開されると、参照されているすべてのプロジェクトおよびパッケージのコンパニオン アセットが、_content/{PACKAGE ID}/
の下の公開済みアプリの wwwroot
フォルダーにコピーされます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の <PackageId>
) と同じではない場合は、発行されたアセットの wwwroot
フォルダーを調べるときに、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
その他のリソース
Razor ビュー、ページ、コントローラー、ページ モデル、Razor コンポーネント、ビュー コンポーネント、データ モデルは、Razor クラス ライブラリ (RCL) に組み込むことが可能です。 RCL はパッケージ化し、再利用できます。 アプリケーションには RCL を含めることができます。また、それに含まれるビューやページをオーバーライドできます。 Web アプリと RCL の両方にビュー、部分ビュー、Razor ページがあるとき、Web アプリの Razor マークアップ ( .cshtml
ファイル) が優先されます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
Razor UI を含むクラス ライブラリの作成
- Visual Studio の [ファイル] メニューから、[新規作成]>[プロジェクト] の順に選択します。
- [ASP.NET Core Web アプリケーション] を選択します。
- ライブラリに名前を付け ("RazorClassLib" など)、>[OK] を選択します。 生成されたビュー ライブラリとファイル名の競合を避けるため、ライブラリ名の末尾が
.Views
ではないことを確認します。 - ASP.NET Core 2.1 以降が選択されていることを確認します。
- [Razor クラス ライブラリ]>[OK] の順に選択します。
RCL には次のプロジェクト ファイルがあります。
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
RCL に Razor ファイルを追加します。
ASP.NET Core テンプレートでは、RCL コンテンツが Areas
フォルダーにあるものとしています。 ~/Areas/Pages
ではなく ~/Pages
でコンテンツを公開する RCL を作成する場合は、「RCL ページのレイアウト」を参照してください。
RCL コンテンツを参照する
RCL は次によって参照できます。
- NuGet パッケージ。 「Creating NuGet packages」 (NuGet パッケージの作成)、「dotnet add package」、「Create and publish a NuGet package」 (NuGet パッケージの作成と公開) を参照してください。
{ProjectName}.csproj
: 「dotnet-add reference」を参照してください。
チュートリアル: RCL プロジェクトを作成し、Razor Pages プロジェクトから使用する
作成しなくても、完全なプロジェクトをダウンロードしてテストできます。 サンプル ダウンロードには、プロジェクトのテストを簡単にする追加のコードやリンクが含まれています。 GitHub の問題に関するフィードバックはこちらで扱っています。ダウンロード サンプルと段階的指示の違いについてコメントを投稿できます。
ダウンロード アプリをテストする
完全なアプリをダウンロードしておらず、チュートリアル プロジェクトを作成する場合、次のセクションに進んでください。
Visual Studio で .sln
ファイルを開きます。 アプリを実行します。
テスト WebApp1 の指示に従ってください。
RCL を作成する
このセクションでは、RCL が作成されます。 Razor ファイルが RCL に追加されます。
RCL プロジェクトの作成:
- Visual Studio の [ファイル] メニューから、[新規作成]>[プロジェクト] の順に選択します。
- [ASP.NET Core Web アプリケーション] を選択します。
- アプリに RazorUIClassLib という名前を付け、>[OK] を選択します。
- ASP.NET Core 2.1 以降が選択されていることを確認します。
- [Razor クラス ライブラリ]>[OK] の順に選択します。
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
という名前の Razor 部分ビュー ファイルを追加します。
Razor ファイルとフォルダーをプロジェクトに追加する
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
のマークアップを次のコードに変更します。<h3>_Message.cshtml partial view.</h3> <p>RazorUIClassLib\Areas\MyFeature\Pages\Shared\_Message.cshtml</p>
RazorUIClassLib/Areas/MyFeature/Pages/Page1.cshtml
のマークアップを次のコードに変更します。@page @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <h2>Hello from a Razor UI class library!</h2> <p> From RazorUIClassLib\Areas\MyFeature\Pages\Page1.cshtml</p> <partial name="_Message" />
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
は部分ビュー (<partial name="_Message" />
) を使用するために必要です。@addTagHelper
ディレクティブを含める代わりに、_ViewImports.cshtml
ファイルを追加できます。 次に例を示します。dotnet new viewimports -o RazorUIClassLib/Areas/MyFeature/Pages
_ViewImports.cshtml
の詳細については、「共有ディレクティブのインポート」を参照してくださいクラス ライブラリをビルドし、コンパイラ エラーがないことを確認します。
dotnet build RazorUIClassLib
ビルド出力には RazorUIClassLib.dll
と RazorUIClassLib.Views.dll
が含まれています。 RazorUIClassLib.Views.dll
には、コンパイル済みの Razor コンテンツが含まれています。
Razor ページ プロジェクトから Razor UI ライブラリを使用します。
Razor ページ Web アプリの作成:
ソリューション エクスプローラーで、ソリューションを右クリックし、[追加]>[新しいプロジェクト] の順に選択します。
[ASP.NET Core Web アプリケーション] を選択します。
アプリに WebApp1 という名前を付けます。
ASP.NET Core 2.1 以降が選択されていることを確認します。
[Web アプリケーション]、[OK] の順に選択します。
ソリューション エクスプローラーで、WebApp1 を右クリックし、 [スタートアップ プロジェクトに設定] を選択します。
ソリューション エクスプローラーで、WebApp1 を右クリックし、[ビルド依存関係]、[プロジェクトの依存関係] の順に選択します。
WebApp1 の依存関係として RazorUIClassLib を選択します。
ソリューション エクスプローラーで、WebApp1 を右クリックし、[追加]、[参照] の順に選択します。
[参照マネージャー] ダイアログで、[RazorUIClassLib]、[OK] の順に選択します。
アプリを実行します。
テスト WebApp1
/MyFeature/Page1
を参照して、Razor UI クラス ライブラリが使用されていることを確認します。
ビュー、部分ビュー、ページのオーバーライド
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 コンテンツを Web アプリの Pages
フォルダーの一部であるかのように参照するには、次のファイル構造で RCL プロジェクトを作成します。
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
RazorUIClassLib/Pages/Shared
に 2 つの部分ファイル (_Header.cshtml
と _Footer.cshtml
) が含まれているとします。 これらの <partial>
タグを _Layout.cshtml
ファイルに追加できます。
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Razor ビュー、ページ、コントローラー、ページ モデル、Razor コンポーネント、ビュー コンポーネント、データ モデルは、Razor クラス ライブラリ (RCL) に組み込むことが可能です。 RCL はパッケージ化し、再利用できます。 アプリケーションには RCL を含めることができます。また、それに含まれるビューやページをオーバーライドできます。 Web アプリと RCL の両方にビュー、部分ビュー、Razor ページがあるとき、Web アプリの Razor マークアップ ( .cshtml
ファイル) が優先されます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
Razor UI を含むクラス ライブラリの作成
- Visual Studio から [新しいプロジェクトの作成] を選択します。
- [Razor クラス ライブラリ]>[次へ] の順に選択します。
- ライブラリに名前を付け ("RazorClassLib" など)、>[作成] を選択します。 生成されたビュー ライブラリとファイル名の競合を避けるため、ライブラリ名の末尾が
.Views
ではないことを確認します。 - ビューをサポートする必要がある場合は、 [ページとビューのサポート] を選択します。 既定では、Razor ページのみがサポートされています。 [作成] を選択します。
Razor クラス ライブラリ (RCL) テンプレートは Razor コンポーネント開発での既定です。 [ページとビューのサポート] オプションによって、ページとビューがサポートされます。
RCL に Razor ファイルを追加します。
ASP.NET Core テンプレートでは、RCL コンテンツが Areas
フォルダーにあると見なされます。 ~/Areas/Pages
ではなく ~/Pages
でコンテンツを公開する RCL を作成する場合は、後述の「RCL ページのレイアウト」を参照してください。
RCL コンテンツを参照する
RCL は次によって参照できます。
- NuGet パッケージ。 「Creating NuGet packages」 (NuGet パッケージの作成)、「dotnet add package」、「Create and publish a NuGet package」 (NuGet パッケージの作成と公開) を参照してください。
{ProjectName}.csproj
: 「dotnet-add reference」を参照してください。
ビュー、部分ビュー、ページのオーバーライド
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 で Razor Pages を使用する場合は、ホスティング アプリで Razor Pages サービスとエンドポイントを有効にします。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
RCL ページのレイアウト
RCL コンテンツを Web アプリの Pages
フォルダーの一部であるかのように参照するには、次のファイル構造で RCL プロジェクトを作成します。
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
RazorUIClassLib/Pages/Shared
に 2 つの部分ファイル (_Header.cshtml
と _Footer.cshtml
) が含まれているとします。 これらの <partial>
タグを _Layout.cshtml
ファイルに追加できます。
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
_ViewStart.cshtml
ファイルを、RCL プロジェクトの Pages
フォルダーに追加して、ホスト Web アプリの _Layout.cshtml
ファイルを使用します。
@{
Layout = "_Layout";
}
静的アセットを含む RCL を作成する
RCL では、RCL または RCL の使用アプリで参照できる静的なコンパニオン アセットが必要になる場合があります。 ASP.NET Core では、使用アプリで利用できる静的アセットを含む RCL の作成が可能です。
コンパニオン アセットを RCL の一部として含めるには、クラス ライブラリに wwwroot
フォルダーを作成し、必要なファイルをすべてそのフォルダーに含めます。
RCL をパックすると、wwwroot
フォルダー内のすべてのコンパニオン アセットがパッケージに自動的に含まれます。
Nuget.exe バージョン nuget pack
ではなく、dotnet pack
コマンドを使用します。
静的アセットを除外する
静的アセットを除外するには、目的の除外パスをプロジェクトファイル内の $(DefaultItemExcludes)
プロパティ グループに追加します。 各エントリは、セミコロン (;
) で区切ります。
次の例では、wwwroot
フォルダー内の lib.css
スタイルシートが静的アセットとは見なされず、公開された RCL には含まれていません。
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript の統合
TypeScript ファイルを RCL に含めるには、次の操作を行います。
プロジェクトで
Microsoft.TypeScript.MSBuild
NuGet パッケージを参照します。Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
TypeScript ファイル (
.ts
) をwwwroot
フォルダーの外側に配置します。 たとえば、ファイルをClient
フォルダーに配置します。wwwroot
フォルダーの TypeScript ビルド出力を構成します。 プロジェクト ファイルのPropertyGroup
の内側にTypescriptOutDir
プロパティを設定します。<TypescriptOutDir>wwwroot</TypescriptOutDir>
プロジェクト ファイルの
PropertyGroup
の内側に次のターゲットを追加して、TypeScript ターゲットをResolveCurrentProjectStaticWebAssets
ターゲットの依存関係として含めます。<ResolveCurrentProjectStaticWebAssetsInputsDependsOn> CompileTypeScript; $(ResolveCurrentProjectStaticWebAssetsInputs) </ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
参照されている RCL からコンテンツを使用する
RCL の wwwroot
フォルダーに含まれるファイルは、_content/{PACKAGE ID}/
プレフィックスに基づいて RCL または使用アプリのいずれかに公開されます。 たとえば、アセンブリ名が Razor.Class.Lib
で、そのプロジェクト ファイルに <PackageId>
が指定されていないライブラリの場合、_content/Razor.Class.Lib/
の静的コンテンツへのパスが生成されます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の<PackageId>
) と異なる場合は、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
使用アプリは、ライブラリによって提供される静的アセットを <script>
、<style>
、<img>
、およびその他の HTML タグ付きで参照します。 使用アプリの Startup.Configure
で 静的ファイルのサポートが有効になっている必要があります。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseStaticFiles();
...
}
使用アプリをビルド出力から実行 (dotnet run
) すると、開発環境で、静的な Web アセットが既定で有効になります。 ビルド出力から実行するときに他の環境のアセットをサポートするには、Program.cs
のホスト ビルダーで UseStaticWebAssets
を呼び出します。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
});
}
発行された出力からアプリを実行する (dotnet publish
) 場合、UseStaticWebAssets
の呼び出しは必要ありません。
複数プロジェクトの開発フロー
使用アプリの実行時は、次のようになります。
- RCL のアセットは元のフォルダー内に保持されます。 これらのアセットは、使用アプリに移行されません。
- RCL の
wwwroot
フォルダー内の変更は、使用アプリをリビルドしなくても、RCL がリビルドされた後で、使用アプリに反映されます。
RCL がビルドされると、静的な Web アセットの場所を記述するマニフェストが生成されます。 使用アプリは、実行時にそのマニフェストを読み取って、参照されているプロジェクトおよびパッケージのアセットを使用します。 RCL に新しいアセットが追加された場合は、使用アプリがその新しいアセットにアクセスする前に、RCL をリビルドしてそのマニフェストを更新する必要があります。
公開
アプリが公開されると、参照されているすべてのプロジェクトおよびパッケージのコンパニオン アセットが、_content/{PACKAGE ID}/
の下の公開済みアプリの wwwroot
フォルダーにコピーされます。 NuGet パッケージを生成するときに、アセンブリ名がパッケージ ID (ライブラリのプロジェクト ファイル内の <PackageId>
) と同じではない場合は、発行されたアセットの wwwroot
フォルダーを調べるときに、{PACKAGE ID}
のプロジェクト ファイルで指定されているパッケージ ID を使用します。
その他のリソース
ASP.NET Core