Blazor の学習中に Pages フォルダへ MyButton.razor(@page "/MyPage")を追加したのに、左側メニュー(NavMenu)にリンクが増えない…。これは不具合ではなくテンプレートの仕様です。この記事では、メニューに表示する最短手順と、つまずきやすい確認ポイントをまとめます。
症状:新しく追加した Razor コンポーネントがメニューに出てこない
Blazor のテンプレートを触り始めた直後に、次のような状態になることがあります。
Pagesフォルダに MyButton.razor を追加し、先頭に@page "/MyPage"を書いた- ビルドは通る(ページ自体は存在している)
- しかし、画面左側のナビゲーションメニュー(NavMenu)には新しいリンクが表示されない
- 最初からある「Home」「Counter」「Fetch data(または Weather)」などの 3 つだけが表示され続ける
結論から言うと、ページの追加=メニューの自動追加 ではありません。ルーティングは増えても、メニューは増えないため、手動で NavMenu に項目を足す必要があります。
まず押さえるポイント:原因と対処はシンプル
迷ったときは、いったん次の対応表に戻ると切り分けが早いです。
| 起きていること | 原因 | 対処 | 確認方法 |
|---|---|---|---|
| メニューに MyPage が出ない | NavMenu は自動生成されない | NavMenu.razor に <NavLink> を追記 | 左メニューにリンクが増えたか |
| メニューは出たがクリックしても遷移しない | href と @page が不一致 / ベースパス不一致 | href をルートに合わせる(必要なら相対パスに) | アドレスバーに URL を直接入力して表示できるか |
| 直接入力でも表示できない | @page がない / ビルドエラー | @page を確認、ビルドログ確認 | dotnet build とブラウザ Console |
結論:NavMenu は自動生成されないので、NavMenu.razor にリンクを追記する
Blazor では、@page ディレクティブ(または [Route] 属性)が付いたコンポーネントは URL ルートとして認識されます。一方で、左メニューの NavMenu は「ただの部品」です。テンプレートは NavMenu の中にあらかじめ数個の <NavLink> を固定で書いているだけなので、新規ページを作っても自動で増えません。
| 要素 | 役割 | 自動で増える? | 代表ファイル |
|---|---|---|---|
| ルーティング | @page の情報を見て URL とコンポーネントを結び付ける | 増える(@page を追加すればルートは増える) | App.razor / Routes.razor など |
| NavMenu | 画面に表示する「メニュー項目」を並べるだけ | 増えない(自分でリンクを書き足す) | NavMenu.razor |
対応手順:MyButton(/MyPage)をメニューに表示する
NavMenu.razor を開く
プロジェクトのテンプレートや .NET の世代によって配置が少し違います。まずは「NavMenu.razor」を検索して開くのが確実です。よくあるパスは次のとおりです。
| テンプレート例 | NavMenu の場所(例) | 補足 |
|---|---|---|
| Blazor WebAssembly / Server(従来テンプレート) | Shared/NavMenu.razor | 学習教材や旧テンプレートでよく見かける構成 |
| .NET 8 以降の新しめの構成 | Components/Layout/NavMenu.razor | Components 配下にレイアウト関連がまとまっていることが多い |
| 独自にフォルダを整理している場合 | プロジェクト内検索で NavMenu を探す | レイアウトを自作していると複数存在することも |
既存のメニュー項目を参考に、MyPage 用の NavLink を追加する
NavMenu.razor を開くと、テンプレートの既存リンク(Home/Counter/Fetch data)が並んでいるはずです。その近くに、同じ構造で MyPage 用のリンクを 1 つ追加します。
<div class="nav-item px-3">
<NavLink class="nav-link" href="/MyPage">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span>
MyPage
</NavLink>
</div>
このコードのポイントは次のとおりです。
- href はルートと一致:ページ側が
@page "/MyPage"なら、href="/MyPage"にします。 - 表示名は自由:メニューに表示する文字は「MyPage」でも「現在時刻ボタン」でも分かりやすければ OK です。
- アイコンはテンプレートに合わせる:最近のテンプレートは Bootstrap Icons(
bi ...)を使うことが多い一方、古いテンプレートは Open Iconic(oi ...)の場合があります。見た目だけの差なので、最初はアイコン部分を消しても動作確認はできます。
サブディレクトリ公開の可能性があるなら、相対 href も検討する
開発環境(https://localhost:xxxx/)では href="/MyPage" で問題が出にくい一方、アプリをサブディレクトリ配下(例:https://example.com/app/)で公開する予定があるなら、次のように 先頭スラッシュなしの相対指定が安全なことがあります。
<NavLink class="nav-link" href="MyPage">MyPage</NavLink>
/MyPage は「ドメイン直下」を指すため、ベースパス運用と相性が悪いケースがある、という点だけ覚えておけば十分です。学習モジュールの範囲では、まずは質問文どおり /MyPage で理解してから、公開形態に応じて調整すると迷いません。
ページ側の @page と一致しているかを確認する
「メニューに出ない」原因の大半は、NavMenu の href と、ページの @page が一致していないことです。特に学習中は、ファイル名(MyButton)とルート名(MyPage)がズレていると混乱しやすいので、いったん表で確認しておくと安全です。
| MyButton.razor の先頭 | NavMenu の href | 結果 | コメント |
|---|---|---|---|
@page "/MyPage" | href="MyPage" | OK | ベースパスに追従しやすい |
@page "/MyPage" | href="/MyPage" | OK | ドメイン直下で運用するなら分かりやすい |
@page "/MyPage" | href="/MyButton" | NG | ファイル名とルートを混同している典型例 |
@page "/mypage" | href="/MyPage" | ほぼOK | ルーティングは大抵大文字小文字を吸収しますが、表記ゆれは避けるのがおすすめ |
再ビルドしてブラウザを更新する
NavMenu.razor を保存したら、次を順に実行します。
- プロジェクトを再ビルド(または再実行)
- ブラウザをリロード(開発中に反映されない場合は強制更新)
- 左メニューに「MyPage」の項目が増えていることを確認
Hot Reload が効いている環境でも、レイアウト周りの差分が UI に反映されないことがあります。その場合は「いったん停止→再起動」「ブラウザの強制再読み込み(Ctrl+F5 / Shift+Reload)」までやると切り分けが早いです。
補足:メニューに追加しなくてもページにアクセスできる理由
NavMenu にリンクがなくても、ページが「存在しない」わけではありません。@page を書いた時点でルーティングは有効になっているため、アドレスバーに https://(あなたのURL)/MyPage と直接入力すれば表示できます。
つまり、今回の問題は「ルートが登録されていない」ではなく、NavMenu が新しいルートを自動的に列挙する仕組みではない、という点に集約されます。
MyButton.razor は「ページ」にも「部品」にもなれる
Blazor の Razor ファイルは、書き方しだいで次の 2 通りの役割を持ちます。
- ページ(ルーティング対象):
@pageを書く。URL で直接開ける。 - 再利用する部品(コンポーネント):
@pageを書かない。他のページから<MyButton />のように呼び出して使う。
「ボタン部品を作っただけなのにメニューに出したい」というケースでは、実は “ページにする必要があるのか” を見直すのも手です。学習目的で動作確認するならページ化(@page あり)で OK、アプリの部品として使いたいならページ化しない(@page なし)方が設計がシンプルになります。
それでも表示されないときのチェックリスト
NavMenu を編集したのに反映されない場合、原因はメニュー追記以外にあることもあります。ここからは、実務でも遭遇しやすい確認ポイントを「短時間で潰せる順」に並べます。
NavMenu を編集しているファイルが「本当に表示されている NavMenu」か
プロジェクトによっては NavMenu.razor が複数あることがあります。例えば、テンプレートをカスタマイズして新しいレイアウトを追加した場合、古い NavMenu を編集しても画面に反映されません。
確認方法の一例として、表示中のレイアウト(多くは MainLayout.razor)を開き、メニュー部分で読み込んでいるコンポーネントを見ます。
<!-- MainLayout.razor の例 -->
<div class="sidebar">
<NavMenu />
</div>
<NavMenu /> が別名(例:<MyNavMenu />)になっていたり、レイアウト自体が切り替わっていたりする場合は、編集対象を見直してください。手早く見分けるなら、NavMenu に一時的に TEST の文字を入れて画面に出るか確認する方法が確実です。
MyButton.razor の先頭に @page があるか
質問文では「@page "/MyPage" を付けた」となっていますが、実際には @page がコメントの下に埋もれていたり、条件付きで無効になっていたりするケースがあります。最小構成の例は次のとおりです。
@page "/MyPage"
<h1>MyPage</h1>
<p>ここにボタンなどを置く</p>
目安として「@page が 1 行目付近にある」状態にしておくと、見落としが減ります。
ビルドエラーが隠れていないか
「画面は開けるがメニューだけ更新されない」ケースでも、実はコンソールに警告やエラーが出ていることがあります。特に、追加した NavLink の中で CSS クラス名を間違えたり、コンポーネント名のタイポがあると、ビルドに失敗して古い状態が表示され続けます。
- IDE のエラー一覧を確認
- ターミナルで
dotnet buildを実行してエラーがないか確認 - ブラウザの開発者ツール(Console)を確認
href の書き方が公開環境のベースパスと合っているか
開発環境では問題なくても、公開形態(IIS/Reverse Proxy/GitHub Pages など)によっては href="/..." が原因で意図しない場所に飛ぶことがあります。心当たりがある場合は、リンク指定を相対に寄せるか、<base href="..."> の設定(テンプレート側)を含めて見直すと改善しやすいです。
NavLink の Match を理解しておく
「リンクは出たが、選択中のハイライトが期待通りにならない」という副作用が出ることもあります。Blazor の <NavLink> は、現在の URL と href の一致度でアクティブ判定をします。
- トップページ(Home)は部分一致だと常にアクティブになりがちなので、
Match="NavLinkMatch.All"を付けるのが定番です。 - それ以外はデフォルト(部分一致)でも問題ないことが多いです。
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
Home
</NavLink>
MyPage 側は通常デフォルトのままでよいですが、「/MyPage」と「/MyPage/Detail」のように子階層を持つ設計にしたい場合は、意図したアクティブ表示になるよう Match の方針を決めておくと UX が整います。
実務で役立つ:NavMenu の追加をミスりにくくする書き方
学習段階では 1 行追加で十分ですが、ページ数が増えると「コピペのズレ」「リンクだけ更新し忘れ」といった事故が起きやすくなります。ここでは、NavMenu を少しだけ整理して、運用しやすくする方法を紹介します。
メニュー項目をリスト化して foreach で描画する
NavMenu にリンクを直書きするのではなく、メニュー定義をリストにしておくと、表記揺れや重複を減らせます。例えば次のように「タイトル」と「URL」を 1 箇所に集めます。
@code {
private readonly (string Title, string Href, string IconClass)[] Items =
[
("Home", "", "bi bi-house-door-fill"),
("Counter", "counter", "bi bi-plus-square-fill"),
("Fetch data", "fetchdata", "bi bi-list-nested"),
("MyPage", "MyPage", "bi bi-list-nested-nav-menu")
];
}
そして描画側は繰り返しにします。
@foreach (var item in Items)
{
<div class="nav-item px-3">
<NavLink class="nav-link" href="@item.Href">
<span class="@item.IconClass" aria-hidden="true"></span>
@item.Title
</NavLink>
</div>
}
この形にすると、次のメリットがあります。
- 追加・削除が「配列に 1 行足す/消す」で済み、編集箇所が減る
- メニュー表示名を変えるときに、誤って
hrefを壊しにくい - チーム開発で差分が読みやすい(レビューしやすい)
一方で、テンプレートの CSS 構造を大きく変えるとレイアウトが崩れることがあるので、まずは「既存の HTML 構造を維持したまま foreach に置き換える」方針が安全です。
メニューに出すページと、出さないページを分ける
実務では、URL は存在するがメニューに出さないページ(例:ログイン後だけ見せる管理画面、詳細画面、ウィザードの中間ページ)も増えます。そうした場合は、NavMenu を「表示したいページだけを書く場所」と割り切るのが分かりやすいです。
- ナビゲーション=ユーザーが迷わないための導線
- ルーティング=アプリ内部の画面遷移の入口
この 2 つを同一視しないことが、Blazor アプリを設計しやすくするコツです。
よくある Q&A
ファイル名が MyButton.razor でも href は MyButton になりますか?
なりません。URL はファイル名ではなく、@page に書いたルートで決まります。ファイル名は「開発者が管理しやすいように付ける名前」で、URL とは独立です。今回の例なら、ファイル名が MyButton でも URL は /MyPage です。
自動でルート一覧を拾ってメニューを生成できませんか?
技術的には可能です(アセンブリから [Route] 属性を持つコンポーネントを反射で列挙する、独自属性でメニュー名を付ける等)。ただし、実務では「並び順」「表示名」「権限による表示/非表示」「アイコン」「グルーピング」などの要件がすぐ増えるため、結局は手動管理に戻るケースが多いです。まずは NavMenu に明示的に書く方法を理解しておくのが近道です。
メニューに追加したのにクリックしても画面が切り替わりません
次の順で確認してください。
- リンク先の URL が正しいか(
hrefと@pageが一致しているか) - ページ側にビルドエラーがないか
- ブラウザの Console に例外が出ていないか
- サブディレクトリ公開の場合、
href="/..."が原因で別の場所へ飛んでいないか
まとめ:Blazor で「ページは増えたのにメニューが増えない」は正常
Blazor では、新しく Razor コンポーネント(ページ)を作って @page を追加するとルーティングは有効になります。しかし、NavMenu はルート一覧を自動で取り込む仕組みではないため、メニューに表示したい場合は NavMenu.razor に <NavLink> を追記する必要があります。
まずは「NavMenu を開いて 1 項目追加」という基本を押さえ、次に「ベースパス運用」「Match」「メニュー管理の整理」に進むと、学習と実務の両方でつまずきにくくなります。

コメント