asp.net-mvc-5 - 未将对象引用设置为对象的实例 - 多个项目 (MVC)

标签 asp.net-mvc-5 entity-framework-6 solid-principles entity-framework-migrations

我正在使用 Contoso 大学教程,并尝试使用模块化尝试(模型、DAL 和 WebUI 的单独项目 - 附图中的顶部图片)和单个项目(包含所有层 - 底部图片)。在这两种情况下,解决方案都可以正确编译。但是,当我在网络浏览器中转到学生的详细信息部分时,当我转到第二个断点时,模块化项目会抛出错误,开始:

异常详细信息:

System.NullReferenceException: Object reference not set to an instance of an object.

相同的模型被传递到每个项目的 View 中,

@model ContosoUniversity.Models.Student

并且在该行之后发生空引用异常:

@foreach (var item in Model.Enrollments){ 

我认为这可能是 ContosoUniversity.Models 项目与 ContosoUniversity 项目中的 Models 文件夹之间的命名空间冲突,但是重命名该文件夹并不能解决此问题。是否有其他与多个项目相关的问题会导致此处遇到空值(Enrollments.cs 未发送到模型),但对于单个项目则不会? 如果代码中有更深入的内容,我可以跟进完整的 View 代码和模型类。

Screenshot of working and non working solutions in VS2015Community

最佳答案

由于这对于新开发人员来说是一个常见的令人困惑的错误,因此我编写了 post on my blog详细解释错误的含义以及如何调试它。 TL;DR:对象引用未设置为对象的实例是一个运行时错误(因此您的项目编译良好),当您期望变量是特定类的实例时,会发生这种错误,但它实际上在运行时解析为 null。

当您从数据库中选择一个对象但没有匹配的对象,或者您忽略了初始化模型上需要初始化的属性(例如列表)时,通常会发生这种情况。根据您发布的代码行,我的猜测是模型本身为空(可能是因为它来自数据库并且您在将其发送到 View 之前没有检查空值),或者 Enrollments 属性为 null,因为您忽略了对其进行初始化,或者如果您的模型是实体类的实例,则它未标记为virtual

每当您从数据库请求特定对象时,您应该始终检查 null 并进行适当处理。例如,如果您正在处理“详细”操作,则您的代码应类似于:

public ActionResult Detail(int id)
{
    var foo = db.Foos.Find(id); // potentially null, if no matching id
    if (foo == null)
    {
        return new HttpNotFoundResult();
    }

    return View(foo);
}

如果模型上有列表样式属性,则应始终通过类构造函数或自定义 getter 对其进行初始化:

public class Foo
{
    public Foo()
    {
        Bars = new List<Bar>();
    }

    public List<Bar> Bars { get; set; }
}

或者

public class Foo
{
    private List<Bar> bars;
    public List<Bar> Bars
    {
        get
        {
            if (bars == null)
            {
                bars = new List<Bar>();
            }
            return bars;
        }
        set { bars = value; }
    }
}

如果您使用 C# 6,最后一个可以简化为:

public class Foo
{
    public List<Bar> Bars { get; set; } = new List<Bars>();
}

最后,如果您正在处理 Entity Framework POCO,则没有必要,只要该属性是虚拟即可:

public virtual ICollection<Bar> Bars { get; set; }

作为延迟加载工具的一部分, Entity Framework 会自动覆盖该属性,使其永远不会为 null,只有在确实没有任何内容时才为空集合。但是,如果您忽略 virtual 关键字,EF 将无法进行必要的覆盖来处理此问题。

总而言之,您需要弄清楚哪个变量是空的,您希望有一个实际值,然后要么进行适当的空检查(无论如何,这都是一个好主意),要么找出为什么它是空的您期望的值。

关于asp.net-mvc-5 - 未将对象引用设置为对象的实例 - 多个项目 (MVC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35554044/

相关文章:

c# - 为什么我的 MVC5 Post Action 模型没有被填充

c# - 如何转换 Entity Framework 6 为我的模型生成 FluentAPI 定义,而不是数据注释? (我在 VS2015 中使用 MySQL)

c# - 使用 WHERE 子句获取可为空列的 SUM

c# - .NET Core 注册具有不同数量参数的原始泛型

json - future 证明 : Is removing a JSON envelope the current best practice?

c# - 无法将 ASP.NET MVC 5 Controller 添加到 VS2013 中的简单 ASP.NET MVC 项目

c# - MVC 5 路由问题 ActionResult 根

asp.net-mvc - 将 .NET MVC 应用程序中的 User.Identity 映射到事件目录用户

entity-framework - Entity Framework 在与 savechanges 相同的事务中执行sqlcommand

c# - 代码契约和继承(覆盖方法的前提条件)