受け側の Default.cshtml も含めて、型が一致するように修正しています。
ViewComponent クラス (LinkButtonsViewComponent.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace YourAppNamespace.ViewComponents
{
public class LinkButtonsViewComponent : ViewComponent
{
private readonly YourDbContext _context;
public LinkButtonsViewComponent(YourDbContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<IViewComponentResult> InvokeAsync()
{
// 年初と翌年初を計算
var startOfYear = new DateTime(DateTime.Now.Year, 1, 1);
var startOfNextYear = startOfYear.AddYears(1);
// 支払月のリストを取得
var paymentMonths = await _context.Payment
.Where(p => p.Posted >= startOfYear && p.Posted < startOfNextYear)
.Select(p => p.Posted.Month) // int 型
.Distinct()
.OrderBy(m => m)
.ToListAsync();
// ビューに渡す
return View(paymentMonths);
}
}
}
View (Views/Shared/Components/LinkButtons/Default.cshtml)
@model IEnumerable<int>
<div class="payment-month-buttons">
@if (Model != null && Model.Any())
{
@foreach (var month in Model)
{
<button type="button" class="btn btn-primary">
@month 月
</button>
}
}
else
{
<p>該当する月はありません。</p>
}
</div>
主なポイント
@model IEnumerable<int>
.Select(p => p.Posted.Month) は int 型を返すため、ToListAsync() の結果は List<int>。- ビューでは
IEnumerable<int> として受け取るのが汎用的で推奨。
ViewComponent の配置
- クラスは
ViewComponents フォルダに置くのが慣例。 - ビューは
Views/Shared/Components/LinkButtons/Default.cshtml に配置。
エラー防止
Model が null または空の場合の表示を追加。DbContext の null チェックをコンストラクタで実施。
このコードをそのままプロジェクトに追加すれば、コンパイル可能で動作する ViewComponent になります。
もし希望があれば、この ViewComponent を Razor ページや MVC ビューから呼び出すサンプルコード も作成できますが、追加しますか?
Powered by Froala Editor