【问题标题】:Null reference exception when generating a url with UrlHelper.Action method使用 UrlHelper.Action 方法生成 url 时出现空引用异常
【发布时间】:2012-01-28 06:47:33
【问题描述】:

由于某种原因,当某些机器人访问该站点时,使用 UrlHelper.Action 方法生成一个 url 会引发来自 System.Web.HttpServerVarsCollection.Get 的空异常。我已经进行了一些调试,调用堆栈起源于试图从HttpContextBase.Request.ServerVariables 集合中获取“HTTP_X_ORIGINAL_URL”。

如果我直接从浏览器访问相同的地址 - 没问题。该页面是服务器,没有记录错误。它似乎只有在被机器人访问时才会发生。

不确定它是否相关,但该站点刚刚迁移到 IIS 7.5。仍在集成模式下使用 .NET 2.0。

查看反射器反转的代码,在Get 方法中直接发生空异常的唯一地方是对this._request.FetchServerVariables 的调用。好像没有正确设置完整的请求。

有没有其他人遇到过这个问题或发现了解决方法?为什么当机器人访问请求时会以不同的方式设置请求?

更新:一些额外的调试表明 HttpServerVarsCollection 及其父 HttpRequest 对象已被释放。现在的问题是——HttpContext.Current返回的Request对象如何在请求完成之前暴露?

HttpServerVarsCollection.Get 方法

public override string Get(string name)
{
    if (!this._populated)
    {
        string simpleServerVar = this.GetSimpleServerVar(name);
        if (simpleServerVar != null)
        {
            return simpleServerVar;
        }
        this.Populate();
    }
    if (this._iis7workerRequest == null)
    {
        return this.GetServerVar(base.BaseGet(name));
    }
    string serverVar = this.GetServerVar(base.BaseGet(name));
    if (string.IsNullOrEmpty(serverVar))
    {
        // Only place null reference can happen
        serverVar = this._request.FetchServerVariable(name);
    }
    return serverVar;
}

完整的堆栈跟踪

NullReferenceException: Object reference not set to an instance of an object.]
   System.Web.HttpServerVarsCollection.Get(String name) +8645730
   System.Collections.Specialized.NameValueCollection.get_Item(String name) +7
   System.Web.Mvc.PathHelpers.GenerateClientUrlInternal(HttpContextBase httpContext, String contentPath) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\PathHelpers.cs:39
   System.Web.Mvc.PathHelpers.GenerateClientUrl(HttpContextBase httpContext, String contentPath) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\PathHelpers.cs:21
   System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\UrlHelper.cs:136
   System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\UrlHelper.cs:101
   System.Web.Mvc.UrlHelper.Action(String actionName, String controllerName, Object routeValues) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\UrlHelper.cs:51
   www.CmsExtensions.Document(UrlHelper urlHelper, String path) in C:\Dev\Site\www\Code\CmsExtensions.cs:33
   www.CmsExtensions.Document(UrlHelper urlHelper, Document document) in C:\Dev\Site\www\Code\CmsExtensions.cs:20
   www.<>c__DisplayClass17.<Load>b__c(Document d) in C:\Dev\Site\www\Global.asax.cs:251
   Fringine.Cms.DocumentContentParser.ReplaceDocumentRefs(IResolvingDocumentCache cache, Match match) +258
   Fringine.Cms.<>c__DisplayClass4.<ParseContent>b__2(Match m) +17
   System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) +234
   System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator, Int32 count, Int32 startat) +28
   System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) +38
   System.Text.RegularExpressions.Regex.Replace(String input, String pattern, MatchEvaluator evaluator, RegexOptions options) +47
   Fringine.Cms.DocumentContentParser.ParseContent(String content, IResolvingDocumentCache cache) +83
   Fringine.Cms.ResolvingDocumentCache.<Parse>b__0(String d) +21
   Fringine.Cms.DocumentCache.GetParsedData(String id, String content, IDocumentService documentService, Func`2 parser) +216
   Fringine.Cms.ResolvingDocumentCache.Parse(String id, String content) +67
   Fringine.Cms.CachedDocument.GetSummary() +966
   Fringine.Cms.CachedDocument.get_Summary() +19
   ASP.views_document_widget_feeddocumentsummary_ascx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) +841
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Page.Render(HtmlTextWriter writer) +29
   System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) in C:\Dev\Site\MVC\Microsoft\src\SystemWebMvc\Mvc\ViewPage.cs:107
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266

【问题讨论】:

  • HttpContext.Current.Request 在请求完成之前不应被释放。您是否有代码显示using (HttpContext.Current.Request) 或类似的代码?
  • 不...这也是我最初想到的少数几件事之一。我查看了我拥有的所有代码,并且没有对请求对象上的 Dispose 进行显式(或通过使用)调用。然而,我通过更多的调试确定它只发生在 IIS 7 集成模式下 - 而不是经典模式或 ASP.NET 开发服务器。
  • 实际上我只在 IIS 7.5 o Windows 7 & 2008 R2 上确认过。还没有实际测试过 IIs 7.0。
  • 我也遇到了这个问题,但仅限于我网站的某个版本。就我而言,这似乎是二进制文件的问题,而不是 IIS 的配置。
  • 当某些东西被处理掉时会发生这种情况。在我的情况下,对控制器的引用被保留在会话中(我团队中的一个非常糟糕的程序员!)。当稍后在另一个操作中访问它时,它已被释放并引发您引用的异常。

标签: .net asp.net-mvc-2 nullreferenceexception


【解决方案1】:

我遇到了这个问题,但它与 URL 重写模块无关。

在我的例子中,我不小心将 UrlHelper 的一个实例缓存在一个静态字段中,后来的请求遇到了来自早期请求的已处置实例。

【讨论】:

    【解决方案2】:

    我知道这个问题现在已经相当老了,但我最近发现自己处于非常相似的情况,我的 UrlHelper 在 System.Web.HttpServerVarsCollection.Get 上也给了我空引用异常。

    问题确实是 HTTP_X_ORIGINAL_URL 并且这个特定的服务器变量来自 IIS 上的 URL Rewrite 2.0 模块

    有趣的是,该模块已安装但未被使用。然而,仅仅它的存在就足以引起问题。卸载它使错误消失。

    如果您需要重写 URL,还有其他模块,或者您可以在应用程序级别进行。

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      我遇到了这个问题,在我的情况下,可以通过切换到 UrlHelper 的非扩展方法使用来解决。我有一个扩展方法调用另一个,但将 UrlHelper 传递给第二个方法。

      这条路被打破了:

      public static string Script(this UrlHelper helper, string fileName)
      {
          return Asset(helper, "~/js/", fileName);
      }
      
      private static string Asset(this UrlHelper helper, string path, string fileName)
      {
          return helper.Content(string.Format("{0}/{1}/{2}",
                 path,
                 Version,
                 fileName));
      }
      

      这种方式有效:

      public static string Script(this UrlHelper helper, string fileName)
      {
          return Asset(helper, "~/js/", fileName);
      }
      
      private static string Asset(UrlHelper helper, string path, string fileName)
      {
          return helper.Content(string.Format("{0}/{1}/{2}",
                 path,
                 Version,
                 fileName));
      }
      

      注意Asset方法的函数签名差异。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-03
        • 2017-09-18
        • 2013-04-08
        • 2016-07-06
        • 1970-01-01
        相关资源
        最近更新 更多