【问题标题】:NullReferenceException on IIS/ASP.net - out of nowhere?IIS/ASP.net 上的 NullReferenceException - 不知从何而来?
【发布时间】:2012-08-06 13:16:06
【问题描述】:

我目前正在为一家软件公司开发一个网站。我有一种机制,在页面加载后立即运行(在 Page_OnLoad,Masterpage 代码文件中),创建一个自己的类的新实例并从那里运行一个函数。 几个星期以来一切都运行良好,我在网站上工作的页面/区域完全不同,不会以任何方式影响我目前的事业。

于是发生了以下事情: 我在 asp.net 开发服务器上尝试了该网站:一切都很好并且工作正常。所以我将它上传到我的 IIS 服务器。访问网站:一切仍在运行,没有错误。 大约 20 分钟后,我刷新了页面:NullReferenceException,不知从何而来。而现在,无论我做什么,我都无法摆脱它。

这是来自堆栈的消息:

   [NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.]
   EITS.WWW.Helper.cUserLog.TrackUserLog(HttpRequest request) in     C:\EIT\Projekte\eits.ch\www.eits.ch\EITSWeb\www.eits.ch\Includes\cUserLog.cs:72
   EITS.WWW.IndexMaster.Page_Load(Object sender, EventArgs e) in C:\EIT\Projekte\eits.ch\www.eits.ch\EITSWeb\www.eits.ch\Index.Master.cs:22
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +24
   System.Web.UI.Control.LoadRecursive() +70
   System.Web.UI.Control.LoadRecursive() +189
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3063

母版页代码文件:

http://codetidy.com/3244/

被调用的类:

http://codetidy.com/3245/

【问题讨论】:

  • 您是否尝试在 cUserLog.cs 的第 72 行附近添加粒度日志记录?理想情况下,将每个复合操作分解为步骤,以便您可以看到它何时失败等? (注意:不要相信行号是精确的——它们可能会有点不同,但应该接近
  • 问题是,当我使用中断调试代码/一步一步地移动代码时,一切运行正常。
  • @user1450661:“当我使用中断调试代码/逐步浏览代码时,一切运行良好”。我假设你在你的开发机器上这样做,因为我怀疑你在生产网络服务器上运行 Visual Studio。但不是直播服务器的问题吗?大概代码是一样的,但是数据呢?如果您有不同的数据库进行调试,则不能假设正在执行相同的代码分支。
  • 感谢您提供该链接。那里非常有用的信息!但我肯定知道 NullReferenceException 是什么,以及导致它的原因。但我不明白为什么我的实例在这种情况下为空,错误发生的地方主要是:为什么它完全突然发生?

标签: c# asp.net iis web-applications webserver


【解决方案1】:

这是引发异常的代码部分:

String vSQL = "SELECT * FROM eits_visitor WHERE ip = '" + oUser.usrIP + "'";
DataTable dtCurrent = SQLCon.GetDataTableFromSQL(vSQL, oHelper.cfgConnection);

if (dtCurrent != null && dtCurrent.Rows.Count > 0) {
    // Check if IP is registered today
    vSQL = "SELECT TOP(1)* FROM eits_log WHERE visitor_ip = '" + oUser.usrIP + "' ORDER BY date DESC;";
    dtCurrent = SQLCon.GetDataTableFromSQL(vSQL, oHelper.cfgConnection);

    // Next line is where the exception is thrown:
    if (SQLCon.DateFromString(dtCurrent.Rows[0]["date"].ToString()).DayOfYear != DateTime.Now.DayOfYear) {
        // do stuff
    }
}

问题在于第二个查询,您没有检查 dtCurrent.Rows[0] 是否存在。

在第一个查询中,您正在做正确的事情 - 在做任何事情之前检查 dtCurrent.Rows.Count > 0。您似乎只是假设因为第一个查询返回了结果,所以第二个查询也将返回,但由于这是引发异常的地方,您可能需要重新考虑该假设。

您的评论说第二个查询旨在“检查 [ing] 是否今天注册了 IP”,但您实际上并没有检查记录是否存在 - 您只是假设记录存在并使用它,这在没有这样的记录时使代码失败。

如果IP今天没有注册,还有记录吗?如果没有,那就是你的问题所在。

我对此类问题的第一反应是添加检查以确保我的假设是正确的:

if (dtCurrent.Rows.Count == 0)
    throw new Exception("The unthinkable happened - our assumption was wrong!");

// Next line is where the exception was being thrown before.
// Do we still get this far now?
if (SQLCon.DateFromString(dtCurrent.Rows[0]["date"].ToString()).DayOfYear != DateTime.Now.DayOfYear) {
    // do stuff
}

【讨论】:

  • 不,这不是问题,因为总是有记录,所以第二个查询总是返回一行。当我使用中断来浏览我的代码时,我得到了一个结果行,其中包含我所期望的信息。
  • 如果情况确实如此(在我看来它仍然是有风险的代码),您需要在继续之前查明哪个对象实际上为空。对于以“if (SqlCon.DateFromString(...”) 开头的行,您会收到 NullReferenceException,但该行上有多个对象,您需要在解决问题之前查明实际为空的对象。是 SQLCon ? dtCurrent? dtCurrent.Rows[0]? dtCurrent.Rows[0]["date"]? 尝试分离步骤找出哪个项目为空,然后您就可以弄清楚为什么它是空的。这是处理空异常的一种很好的通用方法。
  • 附注“总是有记录”是那些很容易导致您遗漏某些东西的假设之一。 一个您的代码假设一定是不正确的,否则您不会得到这个异常。你真的确定这个特定的假设不是问题的根源吗?可能值得仔细检查该记录是否确实存在。
  • 我理解你的想法,但我所能做的就是尝试证明我的假设(即使它“危险”),在这种情况下总是存在记录。如果我浏览我的代码并来到那一行:Voilà,我(如我所料)得到了一排。 SQLCon 在这里,dtCurrent 中有项目,dtCurrent.Rows[0] 也有,并且日期字段返回一个有效的日期,它也被正确地解析为一个字符串。考虑到您的建议并仔细检查仍然导致 NRException 的所有内容,让我假设错误在其他地方,而 ASP.net 只是给出了他的“易于理解、简单的错误消息”(讽刺)
  • 所以你的开发版本正在查找一个记录,并且正在工作,然后你假设当实时版本查找一个完全不同的记录时,它必须仍然找到它。同样,我强烈建议您停止使用调试器单步执行开发版本,而是插入一些语句以绝对确定实时版本确实找到了记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多