【问题标题】:NullReferenceException on if statement with only a bool check仅带有布尔检查的 if 语句上的 NullReferenceException
【发布时间】:2014-11-22 05:41:31
【问题描述】:

我在使用实时 ASP.NET MVC 3 应用时遇到了“奇怪”的情况。使用 X 小时后,生产开始出现错误。我无法在我的开发机器上重现该错误。

这是我的控制器动作签名:

[HttpPost]
public ActionResult AddBanking(int id, int? page, int bankId, 
    string q, int? searchFlag, string query, string accountNo, 
    string accountManager, bool? personnal, int? branchId, 
    int? selectedId, BankSearchModel data)

基本思想是控制器用于View上的两种形式,一种用于搜索searchFlag是隐藏字段的位置,另一种用于添加,这是一个基本的代码结构。

try
{
  if (searchFlag.HasValue)
  {
    var vm = svc.FetchBanks(bankId, q);

    return View(vm);
  }
  else
  {
     bool valid = true, isIndividu = false;

     // some code

     if(!valid) // <- this is where the line 106 is 
     {
     }
  }
}
catch(Exception ex)
{
  ex.Data.Add("context", "AddBanking - THIS IS IT");
  Log.Error(ex);
  return RedirectToAction("Error", new { id = 0 });
}

该错误发生在应用程序长时间完美运行后,突然间,该异常被捕获,但是当用户提交第一个表单(用于搜索-> searchFlag = 1)时,因此在我的示例中输入第一个 if 语句。

这是错误和堆栈跟踪

context: AddBanking - THIS IS IT

    Message: Object reference not set to an instance of an object.
    Stack:
      at XYZ.Controllers.BanksController.AddBanking(Int32 id, Nullable`1 page, Int32
 bankId, String q, Nullable`1 searchFlag, String query, String accountNo, String 
accountManager, Nullable`1 personnal, Nullable`1 branchId, Nullable`1 selectedId, 
BankSearchModel data) in E:\Projects\XYZ\ABC\123.Web\Controllers\BanksController.cs:line 
106
  1. 如何在带有不可为空的 bool 的 if 语句上引发异常?
  2. 由于在我的第一个 if 块中有一个 return View(),并且我 100% 确定它进入了那里,为什么异常出现在第 106 行,执行甚至不应该去那里。
  3. 这是在经过长时间的生产之后才发生的事情,昨天(8 到 5 点)这个过程有效,今天早上抛出异常,但仅在生产中(Windows 2008,ASP.NET MVC 3)。从我的开发机器上,使用相同的数据库和相同的数据发布到页面正在工作。

我的主要问题,我想如何调试它,起初我认为堆栈跟踪没有返回正确的行号,所以我在操作中添加了一个 try/catch,但它仍然返回 if(!有效)作为 NRE...

我将不胜感激任何想法/指导方针。当然,我可以将动作中的两个过程分开,它可能会解决问题,但我更想了解我在示例中做错了什么。

编辑:我完全一无所知 当我问这个问题时,页面没有任何更改代码并且发布的数据完全相同。

编辑 2 @ 10:30 2011/06/01

感谢您的建议,但我真的认为这真的很难找到。该错误今天确实再次出现,但该应用程序从我昨天发布此问题后的 1 小时到今天上午 10 点运行。

这里有更多关于我到目前为止所做的工作以试图了解正在发生的事情:

  1. 我已使用 .pdb 文件重建了应用程序(未更改代码,并重新部署 bin、视图)。
  2. 我已经将 try/catch 放在执行应该采用的每条路径上,这里是确切的场景:

查看:

@using (Html.BeginForm())
{
  @Html.ValidationSummary()

  <fieldset>
  @Html.Hidden("searchFlag", 1)
  @Html.Textbox("q")
  <input type="submit" value="Chercher" /></td>
  </fieldset>
}

svc 不能为空,因为我将它设置在控制器上,如下所示:

[Authorize]
public class BanksController : BaseController
{
  BankService svc = new BankService();
  ...
}

FetchBanks 方法

public BankSearchModel FetchBanks(int bankId, string query)
{
  return Execute<BankSearchModel>(db =>
  {
    try
    {
      // some linq stuff
    }
    catch(Exception ex)
    {
      XYZ.Log.Error(ex); // <= note1
  }, "Error returned by Execute");
}

我的执行方法

protected static T Execute<T>(Func<XYZDbContext, T> query, string errorMessage, bool deferredLoading)
{
  try
  {
    using (XYZDbContext db = new XYZ...())
    {
#if DEBUG
      db.Log = new DebuggerWriter();
      db.CommandTimeout = 3 * 60;
#endif
      if (!deferredLoading)
        db.DeferredLoadingEnabled = false;

      return query(db);
    }
  }
  catch (Exception ex)
  {
#if DEBUG
    Debug.WriteLine(ex.Message + "\r\n" + ex.StackTrace.ToString());
    throw;
#else
    ex.Data.Add("context", "Manager, executing query");
    XYZ.Log.Error(ex); 
    return default(T);
#endif
  }
}

所以,我知道第 106 行并不是真正的错误,但我在每个方法中都有 try/cath,当 searchFlag 设置为 1 时(从第一种形式的视图。我得到的唯一 Log.Error(ex) 仍然是在第 106 行告诉我我的控制器出现错误的那个。

注意 1 如果错误来自 FetchBanks 方法,它会进入该方法中的 catch 并向我发送电子邮件,其中包含该方法的堆栈跟踪。

在我的 FetchBanks 结束时,我返回一个 BankSearchModel,它作为所有列表,因此所有数据库查询都在返回控制器之前执行。

再说一遍,整天发布的相同数据怎么会突然停止工作。带有我所有空对象的控制器的签名会导致这种行为吗?

这是我在到处添加 try/catch 后收到的唯一一封应该向我发送错误的电子邮件。即没有其他方法进入它们的捕获(执行,FetchBanks)只有控制器动作。我真的很想了解发生了什么。

New error occured at 6/1/2011 9:48:13 AM

context: AddBanking - THIS IS IT

Message: Object reference not set to an instance of an object.
Stack:
  at XYZ.Web.Controllers.BanksController.AddBanking(Int32 id, Nullable`1 page, Int32 

bankId, String q, Nullable1 searchFlag, String query, String accountNo, String accountManager, Nullable1 personnal, Nullable1 branchId, Nullable1 selectedId, BankSearchModel 数据)在 E:\Projects\HiddenForObiousReason\Controllers\BanksController.cs:106 行

【问题讨论】:

  • 显然,该 if 语句不会引发异常。您可能在源文件和二进制文件或 PDB 文件之间存在不匹配。重建应用程序(在 DEBUG 配置中),重新部署并希望重现。请务必包含 .PDB 文件。
  • PDB 已经在服务器上,但我正在使用发布模式进行部署。我知道这一行“可能”是引发异常的行: var vm = svc.FetchBanks(bankId, q);但我在那个方法“FetchBanks”中有一个 try/catch,如果是这样的话,它应该记录任何异常......
  • 正如 John 所提到的,CLR 似乎很困惑并报告了不正确的行号。重建您的解决方案 (Clean/RebuildAll) 并重试。它有时会发生。

标签: c# asp.net-mvc-3 nullreferenceexception


【解决方案1】:

将我的操作分成两个不同的操作(对于视图中的两个表单)后,我发现错误与第二个表单有关,并且与通过的模型的验证有关。

这是我现在的两个操作:

[HttpPost]
public ActionResult AddBanking(int id, int? page, int bankId, string q)

[HttpPost]
public ActionResult CreateBanking(int id, int? page, int bankId, string query, string 
accountNo, string accountManager, bool? personnal,
int? branchId, int? selectedId, BankSearchModel data)

发布第一个表单时引发错误,但 Html.ValidationSummary 没有将任何错误写入视图。分离操作后,第一个表单上没有抛出错误,但仅在第二个表单上,现在 ValidationSummary 正在写入视图。这是正常的,我知道第一个表单现在不验证模型。

我仍然无法完全理解为什么每天一次(从上午 8 点到下午 5 点)每次 15 分钟都会出现错误。如果有人有解释,我将不胜感激。为什么具有完全相同数据的表单帖子可以工作,后来却不工作(这两个帖子应该失败,因为模型验证是错误的原因)。

对于两个不同的功能有 1 个操作可能是我的错误。

【讨论】:

    【解决方案2】:

    要对此进行调试,请检查对象是否为空。

    我不会太担心第 106 行,请检查代码中的对象是否为空。

    例子:

    if (svc == null)
    {
        Log.Error(new Exception("svc is null!"); 
    }
    

    您在该方法调用中有很多字符串,如果未分配字符串,则默认为 null,因此这也可能是错误的根源。

    【讨论】:

    • svc 不能为 null,它被实例化为 Controller 类上的受保护变量。 (穷人的DI)。至于空字符串,第一个 if 中使用的唯一字符串是“q”,我看到用户输入一个字符串并通过 SharedView 获取错误。由于第一个 if 中有一个返回视图,我会认为 else 块没有被评估?是的,我确定它进入了 if 语句。此代码几乎每天 22 小时工作。在我在这里写问题时的 SharedView 会话之后,我使用与用户完全相同的数据“q”重新测试,并且它有效(不重新构建,不部署)
    • 如果错误是个谜,我仍然会在此方法中添加额外的调试/跟踪以查看变量的内容。您可以在 catch 中执行此操作以避免性能下降,并让它调用另一个方法来写出所有变量,并将每个变量测试为 null 以查看哪个变量引发了 null refrence 异常。然后一旦问题解决,取出异常中的附加日志。我认为这是你解开谜团的最佳选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 2019-06-30
    • 1970-01-01
    • 2014-02-02
    • 2020-08-20
    • 1970-01-01
    • 2023-01-19
    相关资源
    最近更新 更多