【问题标题】:Global_asax_BeginRequest - How does this line error?Global_asax_BeginRequest - 这行错误怎么办?
【发布时间】:2019-04-10 12:42:51
【问题描述】:

我在 Global.asax.vb 中定义了以下内容...

Private Sub Global_asax_BeginRequest(sender As Object, e As EventArgs) Handles Me.BeginRequest
    Try
        If Request IsNot Nothing Then 'this line throws an exception...
            With Request
                ...

错误是...

错误 - Global_asax:System.NullReferenceException: 对象引用 未设置为对象的实例。

我对这条特定的行如何出错感到有点困惑。我要做的就是测试对象是否为空/无。

我猜当请求开始时,幕后肯定有其他事情发生,但我不知道如何进一步调试它。

此错误并非每次都会发生。我只是偶尔在日志中看到这些错误,我不知道它们是如何发生的。我无法重现它。由于无法访问 Request 对象,我无法获得有关导致它的请求类型的任何其他信息。

更新...

我尝试更改访问 Request 属性的方式,看看是否会有所不同...

Public Sub Application_BeginRequest(sender As Object, e As EventArgs)
    Dim app As HttpApplication = TryCast(sender, HttpApplication)
    If app IsNot Nothing Then
        Dim _request = app.Request
...

这一次,有趣的是,异常发生在这一行……​​

Dim app As HttpApplication = TryCast(sender, HttpApplication)

这看起来很奇怪,因为 TryCast 专门用于不抛出异常。

这是我得到的完整堆栈跟踪...

System.NullReferenceException: Object reference not set to an instance of an object.
     at Global_asax.Application_BeginRequest(Object sender, EventArgs e) in C:\vs_agent\_work\4\s\...\Global.asax.vb:line 97
     at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
     at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
     at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

第 97 行对应 TryCast 行。

我目前的理论是它可能与 Owin 中间件有关

【问题讨论】:

  • 你能添加堆栈跟踪和错误详细信息吗?您使用的 Request 可能与可用的 Request 属性不同。另外方法名通常使用Application_BeginRequest,我从未见过像Global_asax_BeginRequest这样的。
  • 据我所知,无论是使用 Handles Me.BeginRequest 还是 Application_BeginRequest 定义,它都做同样的事情。我似乎找不到任何关于哪种方式更可取的信息。在 Visual Studio 中,如果我让它为我创建函数存根,通过单击“Global_asax Events”->“BeginRequest”,这就是它的定义方式。
  • 由于某种原因,我目前在日志中没有堆栈跟踪。我要做的是添加额外的日志记录,如果我能获得更多信息,请在此处更新。
  • @TetsuyaYamamoto 我刚刚确认没有可用的堆栈跟踪。我所包含的是我能得到的所有细节。我尝试更改为 Application_BeginRequest,但错误仍然完全相同。此外,“请求”只是标准的应用程序属性。范围内其他任何地方都没有其他“请求”。
  • 如果您使用Application_BeginRequest 或仅使用Global_asax_BeginRequest,您是否遇到过错误?您是否为后者正确注册了活动?

标签: asp.net vb.net asp.net-mvc-5


【解决方案1】:

所描述的情况似乎是不可能的(我稍后会解释),我会推荐更多的防弹诊断,例如

Try
  Dim locReq As HttpRequest = Request
Catch ex As Exception
   'record Exception with the complete stack trace
    Throw
End Try 

并使用 HttpRequest 变量 (locReq) 而不是 Request 属性。 sn-p 还可以防止更改 Request 属性的返回值。

为什么我认为你的假设是不可能的:

无法在行中获取NullReference

If Request IsNot Nothing ...

但它可能来自 Request 属性的深度。它的(翻译)source code

Public Class HttpApplication
'...
    Public ReadOnly Property Request As HttpRequest
        Get
            Dim request As HttpRequest = Nothing
            If _context IsNot Nothing AndAlso
                 Not _hideRequestResponse Then request = _context.Request

            If request Is Nothing Then Throw New HttpException(SR.GetString(SR.Request_not_available))
            Return request
        End Get
    End Property

这里又是一个带有(翻译的)source code 的属性请求

Public NotInheritable Class HttpContext
    '...
    Private _response As HttpResponse
    '...
    Public ReadOnly Property Response As HttpResponse
        Get
            If HideRequestResponse OrElse
               HasWebSocketRequestTransitionCompleted Then Throw New 
                  HttpException(SR.GetString(SR.Response_not_available))
            Return _response
        End Get
    End Property

当我阅读代码时,我看不到空引用的空间,但可以有一个 HttpException。所以我的结论是日志系统错误地记录了行或异常。

请查看连接到 Response_not_available 异常的IIS7 Integrated mode: Request is not available in this context exception in Application_Start

编辑

我试图解释显示的堆栈跟踪。我从最深的过程中得出的结论(ExecuteStep(IExecutionStep step, ref bool completedSynchronously) 是异常只能发生在其 catch 块中(用原始 cmets 翻译)。

Catch e As Exception
        [error] = e
        'Since we will leave the context later, we need to remember if we are impersonating
         'before we lose that info - VSWhidbey 494476

        If ImpersonationContext.CurrentThreadTokenExists Then
            e.Data(System.Web.Management.WebThreadInformation.IsImpersonatingKey) = String.Empty
        End If
        'This might force ThreadAbortException to be thrown
        'automatically, because we consumed an exception that was
        'hiding ThreadAbortException behind it

        If TypeOf e Is ThreadAbortException AndAlso ((Thread.CurrentThread.ThreadState And ThreadState.AbortRequested) = 0) Then
            [error] = Nothing
            'Response.End from a COM+ component that re-throws ThreadAbortException
            'It is not a real ThreadAbort
             'VSWhidbey 178556
            _stepManager.CompleteRequest()
        End If
    End Try 

从这里看来,问题确实与中止线程有关。我的猜测是_stepManager is nothing,但我不知道为什么。

【讨论】:

  • 我认为堆栈跟踪中的行号可能是错误的。我可能会尝试在调试的情况下运行生产一段时间,以尝试找出错误发生的确切位置。
  • 我关于行号的理论不正确。这不是问题所在。我关闭了调试,但行号保持不变。我还不知道这一行的异常是如何发生的,但行号似乎是准确的。
  • @user1751825 我已经更新了答案。但这只是对源代码的快速解释。
  • 虽然问题似乎仍然存在,但您的回答帮助我更接近解决问题。
【解决方案2】:

以防万一这对其他人有帮助。

我终于想出了如何重现错误。如果我在没有 User-Agent 标头的情况下拨打电话,就会发生这种情况。就这样……

curl -v -H 'User-Agent:' "https://[my_domain]/"

请求的路径似乎没有任何区别。

我希望我能找到一种方法在没有用户代理的情况下阻止所有请求,然后希望这能解决问题。

但我不太明白,为什么 Request 在 Application_BeginRequest 中不可用,但在 Application_Error 中可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 2021-08-06
    • 2022-01-22
    • 2012-09-06
    • 1970-01-01
    • 2017-10-13
    • 2012-04-14
    相关资源
    最近更新 更多