ASP.NET HttpModule在尝试访问Request.Url时失败,出现了NullReference异常。

4

我有一个 HttpModule 用于处理每个 HttpRequest 的自定义逻辑,但是在某些情况下,当我尝试访问 HttpRequest.Url 时会抛出 NullReferenceException 错误。

在访问 Url 之前,我检查了是否存在 HttpContextRequest 对象不为空。以下是堆栈跟踪:

[NullReferenceException: Object reference not set to an instance of an object.] 
    System.Web.Hosting.IIS7WorkerRequest.GetQueryStringRawBytes() +55 
    System.Web.HttpRequest.get_QueryStringText() +76 
    System.Web.HttpRequest.BuildUrl(Func`1 pathAccessor) +42 
    System.Web.HttpRequest.get_Url() +88 
    MyHttpModule.BeginRequestEventHandler(Object sender, EventArgs e) at +xx      
    System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +175 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +168 

我还查看了.NET源代码,但未能找到NullReference的位置: https://referencesource.microsoft.com/#System.Web/Hosting/IIS7WorkerRequest.cs,68b1222d24e7bd28 以下是代码:
public class MyHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += this.BeginRequestEventHandler;
    }

    private void BeginRequestEventHandler(object sender, EventArgs e)
    {
        var httpContext = ((HttpApplication)sender).Context;
        if (httpContext == null || httpContext.Request == null)
        {
            return;
        }

        var url = httpContext.Request.Url;
        // process url
    }
}

虽然这种情况很少见,但只要发生在处理常规的HTTP请求时,看起来就非常关键。


你能否提供一个 [mcve],展示出问题的代码? - Nkosi
当然,我刚刚更新了我的问题,包括MCV示例。 - Mando
错误是发生在最后一行还是访问变量时?堆栈跟踪似乎表明,当尝试访问URL的查询字符串时发生了错误。可能是传入的请求没有查询字符串,而代码尝试访问它。 - Nkosi
您有哪些完整的URL和查询字符串例子会导致这些错误?它们之间是否存在任何模式或共性?这些可能是恶意请求,专门设计来引起错误。 - pmcilreavy
你用的是哪个 .NET 版本?是 4.6.2 吗? - jazzcat
显示剩余2条评论
3个回答

1
从堆栈跟踪中可以看出,当.NET框架试图从上下文中提取查询字符串时,代码失败了。查看代码,似乎异常是由unsafe代码引发的,这意味着某个指针在某处被设置为零。
我认为IIS中存在一个错误,当它处理格式不正确的请求时会触发该错误,例如将空字符编码到查询字符串中,或者类似的情况。
确保安装所有IIS热修补程序https://social.technet.microsoft.com/wiki/contents/articles/19863.list-of-iis-7-5-related-hotfixes-post-sp1-for-windows-7-sp1-and-windows-server-2008-r2-sp1.aspx 此外,您可以尝试使用Request.PathRequest.FilePath而不是URL,或者简单地添加一个try-catch并忽略它。

1

你能尝试从HttpContext.Current获取HttpContext吗?

public class MyHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += this.BeginRequestEventHandler;
    }

    private void BeginRequestEventHandler(object sender, EventArgs e)
    {
        var httpContext = HttpContext.Current;
        ...
    }
}

HttpContext.Current.Request.QueryStringText不起作用,同样的问题。 - Mando
请求没有 QueryStringText 属性;您需要使用 QueryString。例如,string name = HttpContext.Current.Request.QueryString["name"]; - Win
我正在使用公共的HttpRequest.get_Url() +88 属性,即在内部尝试通过 get_QueryStringText() +76 -> BuildUrl(Func1 pathAccessor) +42` 构建URL并失败。 - Mando

0

尝试这样做,应该没有问题:

if (httpContext.Request != null)
{
    if (httpContext.Request.Url != null)
    {
        var url = httpContext.Request.Url;
    }
}

它看起来不可能是Url为空,此外堆栈跟踪指向更深的.NET代码,这意味着在执行行httpContext.Request.Url != null期间会抛出一个NullReff。 - Mando

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接