【问题标题】:Null reference exception in WriteAttributeTo methodWriteAttributeTo 方法中的空引用异常
【发布时间】:2013-10-25 21:29:55
【问题描述】:

以下代码在 str 为 NULL 时给出 NULL 引用错误,但仅在我们的生产服务器上,而不是在我们的开发或测试服务器上。

<div>
<input value="@Html.Raw(str)" />
</div>

这很好用:

<div>
<input value="@str" />
</div>

这样:

<div>
Values is: @Html.Raw(str)
</div>

所以这不是@Html.Raw 不能接受NULL 参数的问题。不过,我不确定在这种情况下它到底返回了什么;但它在一台服务器上与另一台服务器上有所不同。

两者都运行相同版本的 System.Web.Mvc,但我不知道要检查哪些其他 DLL。 System.Web.WebPages 是应该包含崩溃的 MVC 方法的程序集,在两台服务器上是相同的版本。这是 MVC 版本 4; .Net 4.5。

这怎么可能?错误发生在 WriteAttributeTo 方法中,虽然我什至不知道为什么会在这里调用它,因为它使用标准 HTML 输入标签,而不是 @Html.TextBoxFor 帮助器。

编辑 可能有帮助的一件事是,如果其他人尝试将该代码放在他们自己的视图中以查看它是否有效或损坏。至少那时我会知道是我的生产环境还是测试环境的行为异常。

这是完整的堆栈跟踪:

在 System.Web.WebPages.WebPageExecutingBase.WriteAttributeTo(String pageVirtualPath,TextWriter writer,字符串名称,PositionTagged1 prefix, PositionTagged1 后缀,AttributeValue[] 值)在 System.Web.WebPages.WebPageExecutingBase.WriteAttributeTo(TextWriter writer,字符串名称,PositionTagged1 prefix, PositionTagged1 后缀, AttributeValue[] 值)在 System.Web.WebPages.WebPageExecutingBase.WriteAttribute(字符串名称, PositionTagged1 prefix, PositionTagged1 后缀,AttributeValue[] 值)在 ASP._Page_Views_AdminSurvey_TopDown_cshtml.Execute() 中 c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET 文件\root\fdd62ffd\90d151d1\App_Web_xsolwitr.2.cs:第 0 行 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() 在 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() 在 System.Web.WebPages.StartPage.ExecutePageHierarchy() 在 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) 在 System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext 上下文) 在 System.Web.Mvc.ControllerActionInvoker.c_DisplayClass1a.b_17() 在 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter 过滤器,ResultExecutingContext preContext,Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 继续)在 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext、IList`1 过滤器、ActionResult actionResult) 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.c_DisplayClass25.b_22(IAsyncResult asyncResult) 在 System.Web.Mvc.Controller.c_DisplayClass1d.b_18(IAsyncResult asyncResult) 在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass4.b_3(IAsyncResult ar) 在 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) 在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass4.b_3(IAsyncResult 一只老鼠 System.Web.Mvc.MvcHandler.c_DisplayClass6.c_DisplayClassb.b_4(IAsyncResult asyncResult) 在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass4.b__3(IAsyncResult 一只老鼠 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 在 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤, Boolean & completedSynchronously)

【问题讨论】:

  • 字符串值为空?或者是别的什么?也许这个字符串有一些 unicode 弄乱了作者。
  • 只有当它为空时才会发生。通过直接使用 null 而不是变量来测试它;结果相同。
  • 您能否在您的生产服务器上部署的新创建的 MVC4 应用程序(只有一个控制器一个 aciton 一个视图)中重现该问题?或者这个问题只存在于你的真实应用中?如果您可以复制,您可以将您的复制上传到某个地方(github/skydrive/etc)吗?
  • @nemesv,两台服务器都设置为应用程序在 IIS 中是它自己的网站。看不出每个站点的设置有什么不同。我现在将尝试创建一个新应用进行测试。
  • @nemesv,新项目起初在两台服务器上都运行良好。我查了一下,发现新建MVC项目时,引用了Microsoft.AspNet.WebPages v2.0.20710.0。但我的另一个项目是引用 v2.0.20505.0。我更改了引用并重新部署,果然它仅在产品服务器上中断。所以这两个版本的 WebPages.dll 之间一定是有区别的。但是......如果项目引用旧版本,那么为什么该服务器会选择新版本?旧版本位于 bin 文件夹中。会不会在别处找到更新的版本?

标签: asp.net-mvc asp.net-mvc-4 razor


【解决方案1】:

感谢 nemesv 和 Dave A 的帮助,我能够找到问题所在。这是一个两部分的答案。

1) 出现异常的原因似乎是在 Razor 实现中将Html.Raw 组合在一个HTML 属性。当 Razor 视图引擎 遇到 HTML 属性内的文本时,它使用 WebPageExecutingBase.WriteAttributeTo() 方法,甚至如果它只是在普通 HTML 内。以前我的印象是 Razor View Engine 只处理服务器端命令(@ 符号之后的代码)。虽然Html.RawWriteAttibuteTo() 都允许空值,但需要特殊处理来处理组合2,如果有空值,代码就会崩溃。

2) 这已在最新版本的 System.Web.WebPages.dll 中进行了更新/修复,这会导致答案的第二部分。该项目引用了该 dll 的 Ver 2.0.20505.0,并将其部署在项目的 bin 文件夹中。此版本包含错误。

但即使它被项目引用,并且在 bin 文件夹中,测试服务器也没有使用该版本的 DLL 进行程序集绑定。 fuslog.exe 透露它正在绑定一个在 GAC 中注册的程序集,而不是 Ver 2.0.20710.0强>。 QA 服务器在 GAC 中有这个,而生产服务器没有。我不知道 GAC 会覆盖 bin 文件夹中的 dll。

我已更新我的项目以引用最新的 ASPNetMVC 包,其中包括 Ver 2.0.30506.0 网页 dll

【讨论】:

    【解决方案2】:

    这种微小的内部版本号差异真的会产生影响吗?

    当然可以,次要构建通常包含非破坏性更改,但这并不意味着它们不能包含错误。看起来问题出现在 System.Web.WebPages.WebPageExecutingBase 中,因此可以安全地假设 System.Web.dll 版本不匹配可能是问题的根源。

    您可以通过反汇编程序运行这两个 DLL,并查看该区域及其周围是否有任何明显的变化,但是,如果您知道该问题已在以后的构建中得到解决,那么只需在您的部署机器上使用它即可。


    有一个issueHtml.Raw 在用于8 月修复的属性中时未正确解码文本有关,不确定这是解决问题的两个版本之间的更改。

    【讨论】:

    • 看起来确实可以解释这一点,但该代码应该在 System.Web.WebPages.dll 中,而不是 System.Web.dll 中。 System.Web.WebPages.dll 部署在我项目的 bin 文件夹中,因此在两台服务器上都是相同的。此外,我们的产品服务器有一个挂起的重启,并且在重启后 System.Web.dll 被更新;问题依然存在。
    • 我刚刚确认两台服务器都在运行该特定代码的更新版本。 Test")" /> 正确地保留了未编码的 HTML,这是已解决的问题。
    【解决方案3】:

    让我们深入研究 Razor 视图引擎:

    当你的动作方法调用时

    return View()
    

    View() 方法返回一个 ViewResult 对象。 ViewResult 对象有一个 ExecuteResult() 方法 -- 负责创建 HTML 文档。 p>

    ExecuteResult() 方法遇到像@Html.Raw 这样的Helper 时,它会检查上下文。在填充属性的情况下,Razor 视图引擎 会通过遵循规则并避免陷入困境来尝试变得聪明(或不愚蠢)。属性值渲染使用的方法是WebPageExecutingBase.WriteAttributeTo()

    如果您查找 WriteAttributeTo() 的签名,您会发现它最后需要一个 ParamArray。同样,我们正在研究抽象方法(未发布),但我怀疑 WriteAttributeTo() 方法的实现没有考虑空数组并引发异常。

    【讨论】:

    • 代码真的不是开源的吗? aspnetwebstack.codeplex.com/SourceControl/latest#src/…。我可以看到,如果 ParamArray 为 NULL,它似乎会崩溃。但这不应该在 system.web.webpages 程序集中吗?在这种情况下,两台服务器都有相同的代码。
    • 但是您的回复绝对有帮助。我以前从不明白 Razor 引擎是这样工作的。我认为服务器只查看了服务器端代码(@);其余的保持原样。我现在看到引擎实际上解析了整个视图,并读入(然后写出)常规 HTML 标记。这解释了为什么至少会调用 WriteAttributeTo()。在我认为它只会被 HTML 助手调用之前。
    • 另一件不清楚的事情...... 工作正常。那应该使用相同的 NULL 参数调用 WriteAttributeValues,不是吗?看来 Html.Raw(null) 只是返回 null...
    • @GendoIkari, 1) 是的,所有代码都在 codeplex 中,但如果你好奇的话,这是一项非常糟糕的跟踪工作。 MSDN 不发布任何信息,所以我们只能自己做。那可能会很痛苦。
    • @GendoIkari, 2) 使用像 Raw 这样的 Helper 和只使用 @var 是有区别的。更简单的方法并不倾向于智能。这是一个简单的解析替换。帮助者试图(太)聪明。
    【解决方案4】:

    非常有趣的问题,很高兴你找到了答案!

    如果由于某种原因您被旧版本的 DLL 卡住,这只是一个快速修复 - 使用空合并运算符 ?? 确保内容永远不会是 null

    <div>
        <input value="@Html.Raw(str ?? "")" />
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 2012-09-29
      • 1970-01-01
      • 2012-01-31
      相关资源
      最近更新 更多