🐦

ASP.NET Razor Pages を最初から(7)

2023/02/15に公開

はじめに

部分ビューの使用方法はわかったが、ビュー自体にロジックを持たせることができない。
部分ビューにロジックを持たせ単独のパーツとして使用することができるビューコンポーネントの作成・使用方法を確認する。

https://learn.microsoft.com/ja-jp/aspnet/core/mvc/views/view-components?view=aspnetcore-7.0

ビューファイルを作成する

ビューコンポーネントは、ロジック部分を持つ*.csファイルとビュー部分の*.cshtmlで構成される。
まずは、ビューファイルの配置場所を確認する。

ビューファイルの配置場所

  • /Views/{コントローラー名}/Components/{ビュー コンポーネント名}/{ビュー名}
  • /Views/Shared/Components/{ビュー コンポーネント名}/{ビュー名}
  • /Pages/Shared/Components/{ビュー コンポーネント名}/{ビュー名}
    ビューコンポーネント自体が、ASP.NET MVCの時代からある機能のため、Viewsフォルダから検索されるようになっているが、RazorPagesを使う場合はPages/Shared/Componentsに配置することになる。

既定のビュー名がDefault.cshtmlになっている。
PriorityListビューコンポーネントを作る場合、
Pages/Shared/Components/PriorityList/Default.cshtmlファイルを作成すればよい。
Default.cshtml

Default.cshtml
@{}
<div>
    <p>This is PriorityList ViewComponents</p>
</div>

ビューコンポーネントのロジックファイルを作成する

ビュークラスファイル

ファイル自体は、通常のC#クラスファイルだがファイル名はビューに合わせる必要がある。
今回作成しているのはPriorityListなのでPriorityListViewComponent.csとする。

配置場所

ロジックを持つ*.csファイルはどこにでも配置できるようだが
オフィシャルに倣い、プロジェクトのトップにViewComponentsフォルダを作成し、そこに配置していく。

最小のViewComponetクラス

PriorityListViewComponent.cs
using Microsoft.AspNetCore.Mvc;
namespace ZennSample.ViewComponents;

public class PriorityListViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync()
    {
        return View();
    }
}

ViewComponentを継承して、Task<IViewComponentResult>を返す、InvokeAsyncメソッドを実装して、View()を返す。
基本的にはこれだけでビューコンポーネントが完成する。

ビューコンポーネントを使用する

Hoge.cshtmlから、PriorityListビューコンポーネントを呼び出してみる。

Hoge.cshtml
@page
@model ZennSample.Pages.HogeModel
@{
    ViewData["Title"] = "Hoge Title";
}

<div>
    <h1>Hoge見出し</h1>
</div>
<partial name="Partial/_HogePartial" for="Product"/>
@await Component.InvokeAsync("PriorityList") @* ここでよびだし *@

タグヘルパーでの呼び出し方法もあるが、ビューコンポーネントに関しては@await Component.InvokeAsyncで呼び出したほうが分かりやすい。

タグヘルパーでの呼び出し

<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>

ビューコンポーネントクラスからビューファイルにデータを渡す

ただのHTMLを表示するだけだと部分ビューと変わらないので、作成したPriorityListViewComponentからDefault.cshtmlにデータを渡して使用する。

PriorityListViewComponent.cs
using Microsoft.AspNetCore.Mvc;
using ZennSample.Models;

namespace ZennSample.ViewComponents;

public class PriorityListViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync()
    {
        var p= new Product
        {
            Number = 2,
            Name = "Test ViewComponent",
            Description = "これはビューコンポーネントのテストです"
        };
        return View(p);
    }
}
Default.cshtml
@model ZennSample.Models.Product;
@{}
<div>
    <p>This is PriorityList ViewComponents</p>
    <ul>
        <li>@Model.Number</li>
        <li>@Model.Name</li>
        <li>@Model.Description</li>
    </ul>
</div>

Hoge.cshtml

コツを掴めてきたのか、問題なく成功した。

ビューコンポーネントに呼び出し時に値を渡す

データベースに接続して何かデータを取り出す仕組みにする場合
呼び出すPageによって特定の条件を付与したいという事はよくありそうな要件だと思う。

PriorityListにint型とstring型の引数を渡して、ProductのNumberとNameに設定を行ってみる。
パラメータを渡す際には、ViewComponentのInvokeAsyncメソッドに引数を設定する。

PriorityListViewComponent.cs
public class PriorityListViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(int number=1, string name="Default Name")
    {
        var p= new Product
        {
            Number = number,
            Name = name,
            Description = "これはビューコンポーネントのテストです"
        };
        return View(p);
    }
}

デフォルト値は必須ではないが、引数無しでも呼び出せるように設定しておく。

Hoge.cshtml
@page
@model ZennSample.Pages.HogeModel

@await Component.InvokeAsync("PriorityList", new{number=100, name="ビュー引数"})

InvokeAsyncの第2引数に、匿名型の形で引数を渡す。
PriorityList

引数として与えた値が表示されている事が確認できた。

https://zenn.dev/akilab/articles/b51864c80bf8ea

Discussion