You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC跨控制器嵌入子视图时模型为空的问题

ASP.NET Core MVC跨控制器嵌入视图并加载数据的解决方案

问题核心

直接用<partial>标签引用Notes/Index.cshtml时,只会渲染该视图文件,不会触发NotesController的Index动作,视图依赖的IEnumerable<NoteRecord>模型未被初始化,因此抛出空引用异常。

三种可行解决方案

1. 使用ViewComponent(官方推荐)

ViewComponent是ASP.NET Core专为复用带逻辑的视图组件设计的特性,完美适配跨控制器场景。

步骤1:创建NotesViewComponent

在项目中新建ViewComponents文件夹,添加NotesViewComponent.cs:

using Microsoft.AspNetCore.Mvc;
using ProgMain.Data;
using ProgMain.Models;
using System.Threading.Tasks;

namespace ProgMain.ViewComponents
{
    public class NotesViewComponent : ViewComponent
    {
        private readonly ApplicationDbContext _context;

        public NotesViewComponent(ApplicationDbContext context)
        {
            _context = context;
        }

        public async Task<IViewComponentResult> InvokeAsync()
        {
            var notes = await _context.NotesSet.ToListAsync();
            return View(notes);
        }
    }
}

步骤2:创建ViewComponent对应的视图

在Views/Shared/Components/Notes/路径下新建Default.cshtml,将原Notes/Index.cshtml的内容复制过来:

@model IEnumerable<ProgMain.Models.NoteRecord>
<h1>笔记列表</h1>
<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.Note)</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>@Html.DisplayFor(modelItem => item.Note)</td>
                <!-- 其他列内容 -->
            </tr>
        }
    </tbody>
</table>

步骤3:在父视图中调用ViewComponent

修改Home/Frontend.cshtml:

@{
    ViewData["Title"] = "Frontend";
}
<div style="display:flex">
    <!-- 原有内容 -->
</div>
@await Component.InvokeAsync("Notes")

2. 父控制器获取数据传递给Partial视图

如果不想使用ViewComponent,可以在父控制器动作中获取Notes数据,再传递给Partial视图。

修改HomeController的Frontend动作

using Microsoft.AspNetCore.Mvc;
using ProgMain.Data;
using System.Threading.Tasks;

namespace ProgMain.Controllers
{
    public class HomeController : Controller
    {
        private readonly ApplicationDbContext _context;

        public HomeController(ApplicationDbContext context)
        {
            _context = context;
        }

        public async Task<IActionResult> Frontend()
        {
            var notes = await _context.NotesSet.ToListAsync();
            ViewBag.Notes = notes;
            return View();
        }
    }
}

修改父视图传递模型给Partial

@{
    ViewData["Title"] = "Frontend";
}
<div style="display:flex">
    <!-- 原有内容 -->
</div>
<partial name="/Views/Notes/Index.cshtml" model="@ViewBag.Notes" />

3. AJAX动态加载(适合非服务器端渲染场景)

允许客户端异步加载时,可通过AJAX调用Notes控制器的Index动作,将结果插入父视图。

修改父视图

@{
    ViewData["Title"] = "Frontend";
}
<div style="display:flex">
    <!-- 原有内容 -->
</div>
<div id="notes-container"></div>

<script>
    window.addEventListener('load', function() {
        fetch('/Notes/Index')
            .then(response => response.text())
            .then(html => {
                document.getElementById('notes-container').innerHTML = html;
            });
    });
</script>

注意事项

  • 不要直接将依赖控制器逻辑的视图当作Partial引用,Partial视图本身不具备执行控制器动作的能力。
  • ViewComponent是ASP.NET Core推荐的组件复用方案,支持依赖注入与异步操作,灵活性更高。
  • 若需传递多类数据,建议创建专门的FrontendViewModel封装所有所需数据,避免使用ViewBag/ViewData。

内容的提问来源于stack exchange,提问作者Gigi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:10:38