.NET Core 3.0が正式リリースされたのでBlazor Server触ってみた②

せっかく触ってみたので、ページの追加くらいしてみようと思っていじってみた。

最初はプロジェクトの Pages ディレクトリ下に適当な Test のようなディレクトリを作成し、VSの右クリックメニューから 追加 > Razorページ などしてページを作成したのだが、何か違う気がしたのでやり直した。

結局チュートリアルを参考にMovieモデルを追加する形に落ち着いた。

チュートリアル: 

ASP.NET Core での Razor ページ アプリへのモデルの追加 | Microsoft Docs

おおよそはチュートリアル通りにやればよいのだが、プロジェクトの作成に際して何か設定を間違えたのか、作成したMovies以下のページにスタイルが適用されていない。

レンダリングされたページのHTMLを見てると、とか<HEAD>とかといった必須そうな項目が何1つない。 どうやらページのベースになるレイアウトっぽいものが読み込まれていないようだ。

色々見てみる

とにかく、BlazorとかRazorとか触るのが初めてなので構造がわからない。 もしかしたらそのうち開設されるかもとチュートリアルを一通り流して見るが、特に記述なし。

.cs とか .cshtml とか .razor とか書かれているファイルを片っ端から覗いていく。

関係のありそうなファイル

一通り眺めて関係ありそうだなと思ったのが _Host.cshtmlStartup.cs の2つ。

_Host.cshtml は

@page "/"
@namespace BlazorTest001.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BlazorTest001</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
</head>
<body>
    <app>
        @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
    </app>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>

といった様子で、まさに求めていたベースっぽいものが書かれている。ほかにこれっぽい記述のあるファイルはなかったので、デフォルトで出てくるようなHello world!ページは恐らくこれを読み込んでいるのだろう。

Startup.csチュートリアルなんかでも軽く触れられていたが、実行時の初期化処理を担っているようで、 endpoints.MapFallbackToPage("/_Host"); といった記述があったので、関係ありそうだと踏んだ。

テンプレートの適用されているファイル

実験的に Pages > Movies 以下に、`index.razor をコピーしておいてみる。

indextest.razor のように改名し、内部の @page を修正して実行すると、こちらはきれいに表示される。 どうやら、Moviesページがうまく出ないのは .cshtml.razor とは違う流れでレンダリングされているのが原因らしい。

_ViewStart.cshtml

ほとほと困り果てていろいろ触っていると、スキャフォールディングファイルの作成をするダイアログの中に レイアウトページを使用する > Razor _viewstart ファイルで設定されている場合は空のままにしてください といった記述を見つけた。

察するに新規にビューを作成する際はテンプレートとなるレイアウトを選ぶか、 viewstart なるファイルの設定に従うかを選べるようだ。 しかし、プロジェクト内を検索してみても、 viewstart ファイルは見つからない。どうやら存在しないようだ。

そこで見つけたのがこちらのページ asp.net mvc - _ViewStart.cshtml not found to render embedded cshtml - Stack Overflow

ないなら作ればいいじゃないということのようで、Pages下に作成し、以下のように記述した

@{ 
    Layout = "~/Shared/_Layout.cshtml";
}

同様に _Layout.cshtml ファイルも Shared ディレクトリ内に作成し、 _Host.cshtml の内容をコピーした。

表示できた

改めてページを表示してみると、見事レンダリングは成功していた。

レンダリング成功
画像は残る問題解決後のもの
スタイルシートの設定が違うのか、若干見本と違う気がするが、些細な差だろう。

新たな問題

今度は、 Movies/Create にアクセスすると InvalidOperationException: The following sections have been defined but have not been rendered by the page at '/Shared/_Layout.cshtml': 'Scripts'. To ignore an unrendered section call IgnoreSection("sectionName"). というようなエラーが出るようになった。

要約すると Scriptsセクションが定義されているのにレンダリングされていません ということらしい。

こちらも検索すると @RenderSection("Scripts", false); のように書けばよいことがわかるので、そのようにする。


さしあたって本日はここまで。

とりあえずこれでプロジェクトの作成→モデル定義→ビューの確認までできるようになったことになる。 実はまだ私の環境だとCreateの操作が反映されないなどの問題があるので、追って挑戦したい。