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

ASP.NET Core MVC使用ViewModel报类型不匹配异常如何解决

异常原因

运行时抛出如下异常:

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'SchoolProject.Models.Student', but this ViewDataDictionary instance requires a model item of type 'SchoolProject.ViewModels.StudentViewModel'.

触发的直接原因是类型不匹配:Details动作方法向视图传递的是SchoolProject.Models.Student类型的实体对象,但视图通过@model声明要求接收的模型类型为SchoolProject.ViewModels.StudentViewModel,两者类型不一致就会触发该错误。

正确实现方法

按照ViewModel的使用规范,你需要在动作方法中完成数据查询、ViewModel组装,再将组装好的实例传给视图,步骤如下:

  • 修正Details动作方法逻辑,替换为以下代码:
public async Task<IActionResult> Details(int id)
{
    // 查询指定ID的学生信息
    var student = await _context.Student.FirstOrDefaultAsync(m => m.StudentID == id);
    if (student == null)
    {
        return NotFound();
    }

    // 查询该学生关联的所有课程(通过Enrollment中间表关联)
    var selectedCourses = await _context.Enrollment
        .Where(e => e.StudentID == id)
        .Select(e => e.Course)
        .ToListAsync();

    // 组装StudentViewModel实例,填充视图所需的全部数据
    var studentVm = new StudentViewModel
    {
        Student = student,
        Courses = selectedCourses
    };

    // 将ViewModel实例传递给视图
    return View(studentVm);
}
  • 清理视图冗余代码:视图顶部通过ViewData读取Courses的代码完全没有作用(后续逻辑都是从Model.Courses取数据),可以直接删除:
@{
    IEnumerable<Course> courses = ViewData["Courses"] as IEnumerable<Course>;
}
关键说明
  • ViewModel的核心作用是将单个视图需要的所有数据打包为一个强类型对象,一次性传递给视图,替代弱类型的ViewData/ViewBag传值方式,使用时必须保证 动作方法传入视图的对象类型和视图@model声明的类型完全一致。
  • 如果你希望在查询学生时一次性加载关联的选课数据,可以使用EF Core的关联加载写法,示例如下:
var student = await _context.Student
    .Include(s => s.Enrollments)
        .ThenInclude(e => e.Course)
    .FirstOrDefaultAsync(m => m.StudentID == id);

用这种写法拿到学生实体后,可直接通过student.Enrollments.Select(e => e.Course).ToList()获取关联课程列表,不需要单独写课程查询逻辑,两种查询方式效果一致,按需选择即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:57:22