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

.NET Core中通过分部视图传下拉列表,非首页路由失效问题解决

问题原因

你遇到的问题核心是:_Layout.cshtml 全局引用了分部视图,但只有 Home/Index 这个Action给 ViewBag.Proj 赋值了。当访问其他控制器的Action时,这些Action没有设置 ViewBag.Proj,分部视图渲染时找不到这个变量,直接抛出异常导致网站无法运行。

解决方案

推荐用两种方式解决,优先选第一种(视图组件),因为它是ASP.NET Core官方推荐的复用带逻辑视图的方案,独立性更强:

方案1:使用视图组件(View Component)

视图组件自带独立的业务逻辑,不需要依赖父Action的ViewBag,完全独立生成下拉列表所需的数据。

步骤1:创建视图组件类

在项目中新建一个类(比如放在ViewComponents文件夹下):

public class ProjectDropdownViewComponent : ViewComponent
{
    private readonly YourDbContext _db; // 替换成你的DbContext类名

    // 构造函数注入DbContext
    public ProjectDropdownViewComponent(YourDbContext db)
    {
        _db = db;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        // 查询项目列表,生成SelectList
        var projects = await _db.Projects.ToListAsync();
        var projectSelectList = new SelectList(projects, "ProjectId", "ProjectName");
        return View(projectSelectList);
    }
}

步骤2:创建视图组件对应的分部视图

在Views/Shared/Components目录下,新建ProjectDropdown文件夹,里面创建Default.cshtml:

@model SelectList
<!-- 这里写你的下拉列表HTML,示例如下 -->
<select id="projectDropdown" class="form-control">
    <option value="">请选择项目</option>
    @foreach (var item in Model)
    {
        <option value="@item.Value">@item.Text</option>
    }
</select>

步骤3:在_Layout中调用视图组件

把原来的PartialAsync调用替换成视图组件调用:

@await Component.InvokeAsync("ProjectDropdown")

这样不管访问哪个控制器的Action,视图组件都会自己查询数据生成下拉列表,不会再出现空引用问题。

方案2:使用基础控制器统一赋值

如果不想用视图组件,可以创建一个基础控制器,让所有控制器继承它,在基础控制器的OnActionExecuting方法中统一给ViewBag.Proj赋值,这样所有Action都会自动带上这个变量。

步骤1:创建基础控制器

public class BaseController : Controller
{
    protected readonly YourDbContext _db;

    public BaseController(YourDbContext db)
    {
        _db = db;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // 每次Action执行前都给ViewBag.Proj赋值
        ViewBag.Proj = new SelectList(_db.Projects.ToList(), "ProjectId", "ProjectName");
        base.OnActionExecuting(context);
    }
}

步骤2:让所有控制器继承基础控制器

比如Home控制器:

public class HomeController : BaseController
{
    public HomeController(YourDbContext db) : base(db)
    {
    }

    public IActionResult Index()
    {
        // 这里不需要再设置ViewBag.Proj了,基础控制器已经处理
        return View();
    }
}

其他控制器也一样,都继承BaseController,这样所有视图(包括_Layout引用的分部视图)都能拿到ViewBag.Proj。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:35:57