記事詳細


投稿日
2026年09月29日19時29分
タイトル

ASP.NET Core MVC: MVCアプリでメニューを、データベースのデータから階層ドロップダウンで表示する方法を教えてください [非同期ロード対応(Ajax):親カテゴリ選択時に子カテゴリを動的取得 APIエンドポイント追加:JSONで階層データを返す Viewは初期表示を最小限に:必要な階層だけ読み込む

内容

了解です。
では、前回の多階層ドロップダウン実装を、さらに実務向けに改良して再生成します。
今回は以下の点を追加します。

  • 非同期ロード対応(Ajax):親カテゴリ選択時に子カテゴリを動的取得
  • APIエンドポイント追加:JSONで階層データを返す
  • Viewは初期表示を最小限に:必要な階層だけ読み込む

1. モデル(DBエンティティ)

Csharp
// Models/Category.cs using System.Collections.Generic; using System.ComponentModel.DataAnnotations; public class Category { public int Id { get; set; } [Required] public string Name { get; set; } public int? ParentId { get; set; } public Category Parent { get; set; } public ICollection<Category> Children { get; set; } = new List<Category>(); }

2. DbContext

Csharp
// Data/ApplicationDbContext.cs using Microsoft.EntityFrameworkCore; public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<Category> Categories { get; set; } }

3. サービス(子カテゴリ取得)

Csharp
// Services/CategoryService.cs using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; public class CategoryService { private readonly ApplicationDbContext _context; public CategoryService(ApplicationDbContext context) { _context = context; } public async Task<List<Category>> GetTopLevelCategoriesAsync() { return await _context.Categories .Where(c => c.ParentId == null) .OrderBy(c => c.Name) .ToListAsync(); } public async Task<List<Category>> GetChildrenAsync(int parentId) { return await _context.Categories .Where(c => c.ParentId == parentId) .OrderBy(c => c.Name) .ToListAsync(); } }

4. コントローラー(通常View + API)

Csharp
// Controllers/MenuController.cs using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; public class MenuController : Controller { private readonly CategoryService _categoryService; public MenuController(CategoryService categoryService) { _categoryService = categoryService; } // 初期表示(親カテゴリのみ) public async Task<IActionResult> Index() { var parents = await _categoryService.GetTopLevelCategoriesAsync(); return View(parents); } // API: 子カテゴリ取得 [HttpGet] public async Task<IActionResult> GetChildren(int parentId) { var children = await _categoryService.GetChildrenAsync(parentId); return Json(children.Select(c => new { c.Id, c.Name })); } }

5. View(Ajax連動ドロップダウン)

Html
@model List<Category> <select id="parentCategory" class="form-select"> <option value="">-- 親カテゴリを選択 --</option> @foreach (var parent in Model) { <option value="@parent.Id">@parent.Name</option> } </select> <select id="childCategory" class="form-select mt-2" disabled> <option value="">-- 子カテゴリを選択 --</option> </select> @section Scripts { <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(function(){ $('#parentCategory').on('change', function(){ var parentId = $(this).val(); var $child = $('#childCategory'); $child.empty().append('<option value="">-- 子カテゴリを選択 --</option>'); if(parentId){ $.getJSON('/Menu/GetChildren', { parentId: parentId }, function(data){ if(data.length > 0){ $.each(data, function(i, item){ $child.append($('<option>', { value: item.id, text: item.name })); }); $child.prop('disabled', false); } else { $child.prop('disabled', true); } }); } else { $child.prop('disabled', true); } }); }); </script> }

6. Program.cs

Csharp
using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddScoped<CategoryService>(); builder.Services.AddControllersWithViews(); var app = builder.Build(); app.MapDefaultControllerRoute(); app.Run();

改良ポイント

  1. 初期表示は親カテゴリのみ
    • ページロード時に全階層を読み込まず、軽量化。
  2. Ajaxで子カテゴリ取得
    • 必要なときだけサーバーから取得し、パフォーマンス向上。
  3. APIエンドポイント分離
    • /Menu/GetChildrenでJSON返却、他のUIにも流用可能。

この構成なら、カテゴリ数が多くても高速に動作し、
UIも親カテゴリ選択後に必要な子カテゴリだけ表示できます。

もし希望なら、このAjax版を孫カテゴリまで連動する3階層ドロップダウンに拡張できます。
作りますか?
そうすれば「親 → 子 → 孫」まで自動連動します。

Powered by Froala Editor

添付画像

画像はありません
Genreのカテゴリ-名
Views
編集 | 記事一覧