スイッチブレイザーのインタラクティブ
既存のPower Portals Proプロジェクトをあるインタラクティブモードから別のモードに切り替えるには、 Program.cs、 App.razor、 .Client プロジェクト、そして(インタラクティブ性を追加する際は)アカウントページの一連の編集が必要です。フレームワーク自体は変更を必要としず、ホスト配線だけが変更を必要とします。以下のステップでは、一般的な移行について説明します。
ヒント
カスタマイズがページ数が限られているなら、最も手間が少ないのはターゲットモードで新しいプロジェクトを足場に組み込み、カスタマイズをコピーすることです。手動切り替え後に不一致を追跡する際にも、現在のホストと新たに生成された参照を比較するのが有効です。
dotnet new powerportalspro -o MyPortal-Reference --interactivity Auto
WebAssemblyまたはAuto→サーバー
これらのステップにより、WebAssemblyはサーバー専用ホストに追加されます。WebAssembly専用でもAutoでも同じ編集が適用されます。違いは Program.cs でどのビルダーメソッドを連結するかと、 App.razor がどのレンダリングモードを返すかだけです。どちらもステップごとに指示されます。
1. を変換する。WebAssemblyアプリへのクライアントプロジェクト
.Client/MyApp.Client.csprojを開き、SDKをMicrosoft.NET.Sdk.RazorからMicrosoft.NET.Sdk.BlazorWebAssemblyに変更してください。WebAssemblyフレームワークとPower Portals Proクライアントパッケージを追加してください:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
<PackageReference Include="PowerPortalsPro.Web.Client" />
<PackageReference Include="PowerPortalsPro.Web.Blazor.FluentUI" />
<PackageReference Include="PowerPortalsPro.Web.Common" />
</ItemGroup>
</Project>
WebAssemblyのサーバーサイドホスティングパッケージもサーバーホストの.csprojに加えましょう。WASMバンドルを提供するミドルウェアを提供します。
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
2. サーバー上でインタラクティブなWebAssemblyコンポーネントを登録する
サーバー Program.csでは、コンポーネント登録を対応するビルダーコールに置き換えます。 AddAuthenticationStateSerialization() 認証済みユーザーをServer→WASM境界を越えてシリアライズし、両方のランタイムでカスケード AuthenticationState が一貫性を保つようにします:
// 置き換え
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
// (オート)
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
// または(WebAssembly)
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
3. WebAssemblyのレンダリングモードをマッピングする
app.MapRazorComponents<App>()を更新して、対応するレンダーモードエンドポイントをチェーン化します。AddAdditionalAssemblies呼び出しはすでにテンプレート内の.Clientアセンブリの_Importsを指しているため、ここでは変更されません:
// 自動車
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(MyApp.Client._Imports).Assembly);
// WebAssembly
app.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(MyApp.Client._Imports).Assembly);
4. App.razorのPageRenderModeを更新
App.razorのPageRenderModeゲッターで新しいレンダリングモードを返します。まずInteractiveWebAssemblyRenderMode(prerender: false)にピン/Account/*し、それ以外はデフォルトに戻します:
// In App.razor's PageRenderMode getter
if (HttpContext.Request.Path.StartsWithSegments("/Account"))
return new InteractiveWebAssemblyRenderMode(prerender: false);
// 自動車
return new InteractiveAutoRenderMode();
// WebAssembly
return new InteractiveWebAssemblyRenderMode();
Account-routeのピンが必要なのは、フレームワークの IAuthService がWASMクライアントのDIグラフにのみ登録されているからです。ピンがなければ、Autoのサーバー側プリレンダーはコールドセッションで [Inject] IAuthService を解決できません。
5. 加算 。クライアント/Program.cs
.ClientプロジェクトでProgram.csを作成します。これによりWebAssemblyホストがセットアップされ、クッキー転送ハンドラでHttpClientを登録します(WASMクライアントからの認証呼び出し/api/*ブラウザと同じ認証クッキーを認識し)、WASM側フレームワークサービスを登録するためにAddPowerPortalsProWebClient呼び出しを行います。UserPowerPortalsProWebClient呼び出しは起動時にクロスカッティングローカリゼーション文字列をプリフェッチし、最初のペイント時にキーがフォールバックテキストとして点滅しないようにします:
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.FluentUI.AspNetCore.Components;
using PowerPortalsPro.Web.Blazor.FluentUI;
using PowerPortalsPro.Web.Client;
using PowerPortalsPro.Web.Client.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddFluentUIComponents();
builder.Services.AddSingleton<CookieCredentialsHandler>();
builder.Services.AddHttpClient("PowerPortalsPro", client =>
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<CookieCredentialsHandler>();
builder.Services.AddSingleton(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient("PowerPortalsPro"));
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();
builder.Services.AddPowerPortalsProWebClient();
var app = builder.Build();
await app.UserPowerPortalsProWebClient(
LocalizationBaselines.Default.Concat(new[] { "app" }).ToArray());
await app.RunAsync();
6. フォームポストからJSON認証エンドポイントへの切り替え
サーバーホストはフォームポストのアイデンティティページに MapAdditionalIdentityEndpoints() を使用します。WebAssemblyやAutoホストは代わりに MapAuthEndpoints<TUser>() を使用します。 .Clientの IAuthService ラッパーはこれらのJSONエンドポイントを /api/auth/*以下で呼び出します。
// サーバーのProgram.csに追加してください(アプリの後)。UsePowerPortalsProWebServer)
app.MapAuthEndpoints<PortalUser>();
// オプションでフォーム-postのIdentityエンドポイントをJSONエンドポイントに置き換えることもできます
// (以下の行を削除してください — サーバーレンダリングされたアカウントページだけが消費されます)
// アプリ。MapAdditionalIdentityEndpoints();
ホストがサーバーアカウントページとWASMアカウントの両方を実行している場合(一般的ではありません)、両方のエンドポイント登録が共存します。デフォルトのテンプレートは、インタラクティブモードに応じてどちらか一方を選択します。
7. アカウントページをクライアントプロジェクト
Power Portals Proは、それぞれのレンダリングコンテキストごとに2つの並列したアカウントページセットを出荷しています:
- サーバープロジェクトから
Components/Account/Pages/のサーバーレンダリングページとヘルパークラス(IdentityRedirectManager、IdentityUserAccessor、IdentityComponentsEndpointRouteBuilderExtensions、CookieLoginController)を削除してください。 - WASMアカウントのページを
.Client/Pages/Account/に追加してください。最も速い方法は、新しいプロジェクトを--interactivity Autoでスキャフォールドしてコピーすることです。これにはログイン、登録、パスワード忘れ、リセットパスワード、確認メール、外部ログイン、そして管理/*サーフェス全体が含まれます。 - サーバーレンダリングされたアカウントページ(カスタム検証や追加フィールド)をカスタマイズした場合は、それらのカスタマイズをWASM版に移植してください。WASMは
IAuthServiceUserManagerではなく、同じUXを実装します。
8. オプション — /api/* 用のスコープ付き例外ハンドラ
WebAssemblyが稼働中の場合、/api/*からの例外はRFC 9457 problem+jsonとしてWASMクライアントに往復送され、クライアント側PowerPortalsProService元のCLRタイプをリハイドレートできます。テンプレートはこれにスコープ付き/api/*UseExceptionHandlerを割り当てていて、他の部分では開発者例外ページがサーバーレンダリングされたエラーを処理します。
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
app.UseWhen(
ctx => ctx.Request.Path.StartsWithSegments("/api"),
branch => branch.UseExceptionHandler());
}
WebAssemblyまたはAuto → Server
上記の手順を逆にします:
- サーバーのコンポーネント登録から
AddInteractiveWebAssemblyComponents()とAddAuthenticationStateSerialization()を落とし、保持しておAddInteractiveServerComponents()。 .AddInteractiveWebAssemblyRenderMode()(および隣にチェーンで繋がれたInteractiveServerRenderMode)をMapRazorComponents<App>()のシングル.AddInteractiveServerRenderMode()に置き換えてください。App.razorのPageRenderModeでは、すべてのインタラクティブルートで/Account/*ピンを落としてnew InteractiveServerRenderMode()を戻します。- アカウントページを
UserManager直接パターンでComponents/Account/Pages/のサーバープロジェクトに戻すか(または新しいサーバープロジェクトをスキャフォールドしてコピーします)。IdentityRedirectManager/IdentityUserAccessorを再追加し、.Client/Pages/Account/セットを外してください。 app.MapAuthEndpoints<PortalUser>()をapp.MapAdditionalIdentityEndpoints()に置き換えてください。.ClientプロジェクトのSDKをMicrosoft.NET.Sdk.Razorに戻し、WebAssemblyパッケージの参照を削除し、.Client/Program.csと.Client/wwwroot/を削除してください。
オート↔ウェブアセンブリ
最も安価な切り替えは、プロジェクトのレイアウト、パッケージ、アカウントページが両者で同一です。変わるのは三つだけです。
App.razorのPageRenderModeでは、デフォルトのブランチでnew InteractiveAutoRenderMode()をnew InteractiveWebAssemblyRenderMode()に交換(またはその逆)できます。/Account/*ピンはどちらのモードでも同じままです。- サーバー
Program.csでは、AddRazorComponents()でAddInteractiveServerComponents()を追加または削除できます。Autoには必要ですが、WebAssemblyのみでは必要ありません。 - サーバー
Program.csでMapRazorComponents<App>()で.AddInteractiveServerRenderMode()を追加または削除します。
スイッチの検証
変更後:
- 解決策を作りましょう。 ほとんどの配線ミスはコンパイル時に現れます。例えば、レンダリングモードメソッドの欠落、未解決型、または古いアカウントページの参照などです。
- サインインしてサインアウト。 認証は切り替えが最も厄介なもので、ログイン→プロファイル管理→ログアウトのサイクルをフルに行って、新しいエンドポイントが正しく配線されているか確認してください。
- インタラクティブなページをクリックしてください。 グリッドやエディターのボタンクリックだけで、インタラクティビティが適切な実行時間に達していることが証明されます。サーバーモードは開発ツールのWebSocketタブでSignalR接続を表示します。WebAssemblyはネットワークタブの
/_framework/の下にランタイムファイルを表示します。 - 初回ロード時にWASMバンドルを確認してください。 WebAssemblyやAutoモードでは、新規ロード(シークレットまたはクリアキャッシュ)時のネットワークタブに、ランタイム+フレームワーク+ポータルアセンブリのストリーミングが表示されるはずです。
- アカウントや管理ページを確認してください。 プロフィールの変更、パスワードの変更、外部ログインで各作業を異なるエンドポイントに連携させ、すべてきれいに完了していることを確認してください。
注記
サーバーとWASMクライアント間でサービスを移動する際のサービス寿命の不一致に注意してください。WASMホストはセッションごとに単一のスコープとして動作しますが、フレームワークのキャッシュサービスはシングルトンとして登録されます。WASM側で自分のサービスを
Transientとして登録すると、インスタンスごとにすべてのリゾルブが静かにリセットされます。可変状態を持つサービスにはWASM側のSingletonを使いましょう。
