ASP.NET Core MVC - ビューコンポーネントの呼び出し方色々

ASP.NET Core MVCのビューコンポーネントを試してみました。

ビュー コンポーネント | Microsoft Docs

ビューコンポーネントは従来のASP.NET MVCにあったチャイルドアクション(子アクション、ビューからRenderActionで呼び出していたあれ)の代わりになる機能ですね。呼び出し方が色々あるようなので、ちょっと書き残しておきます。

ビューコンポーネント名を指定する

上記ドキュメントにありますが、ビューコンポーネント名を指定して呼び出す方法があります。試してみましょう。

次のようなビューコンポーネントクラスを用意します。csファイルはプロジェクト直下に「ViewComponents」フォルダを作ってそこに入れるといいのかな?

// 適当なビューコンポーネント
public class Sample1ViewComponent : ViewComponent {
    public async Task<IViewComponentResult> InvokeAsync(int no, string name) {
        // 何か重たい処理があるとして
        await Task.Delay(0);

        // ViewBagも使える(それかViewModelを作るか)
        ViewBag.No = no;
        ViewBag.Name = name;

        return View();
    }
}

続いてビューコンポーネントの呼び出し側。Component.InvokeAsyncメソッドの1つ目の引数にビューコンポーネント名を、2つ目の引数にはSample1ViewComponent.InvokeAsyncメソッドの引数を匿名オブジェクトで指定します。

@await Component.InvokeAsync("Sample1", new { no = 1, name = "Sample1 string" })

型を指定する

typeof演算子で型を指定して呼び出す方法もあります。

@await Component.InvokeAsync(typeof(Sample1ViewComponent), new { no = 2, name = "Sample1 typeof" })

ジェネリック メソッドを使う

ジェネリックジェネリクス?)メソッドが用意されているので、次のような呼び出し方もできます。ただ丸括弧"()"を使う必要があってちょっとだけ残念。ちょいちょい括弧を忘れてコンパイラさんに怒られそう。

@(await Component.InvokeAsync<Sample1ViewComponent>(new { no = 3, name = "Sample1 generics" }))

引数にクラスを使う

ビューコンポーネントを呼び出す引数は、匿名オブジェクトではなく具体的なクラスでも問題なさそうです。

引数が多いという体で引数をクラスにまとめます。

// 適当なビューコンポーネントその2
public class Sample2ViewComponent : ViewComponent {
    // ビューコンポーネントの呼び出しパラメータクラス
    // インナークラスにする必要はないけど
    public class Param {
        public int No { get; set; }
        public string Name { get; set; }
    }

    // 引数にParamクラスを受け取る
    public async Task<IViewComponentResult> InvokeAsync(Param param) {
        // 何か重たい処理があるとして
        await Task.Delay(0);

        ViewBag.No = param.No;
        ViewBag.Name = param.Name;

        return View();
    }
}

呼び出し側もわかりやすいのでこの方法もありかなと思います。

@await Component.InvokeAsync(typeof(Sample2ViewComponent), new Sample2ViewComponent.Param { No = 4, Name = "Sample2" })

コントローラのアクションから呼び出す

ちょっと話は変わりますが、ビューコンポーネントはビューだけでなくコントローラのアクションメソッドでも呼び出せます。Ajaxでも使いたいときですかね。

// ビューコンポーネントを返すアクション
public IActionResult Sample1() {
    return ViewComponent(typeof(Sample1ViewComponent), new { no = 5, name = "Sample1 controller" });
}

こんなところかなと。