asp.net 调用了两次BeginRequest

w3nuxt5m  于 2023-02-01  发布在  .NET
关注(0)|答案(3)|浏览(175)

我创建了一个HttpModule

using System;
using System.Web;

public class TestModule : IHttpModule
{
    public TestModule() {  }

    public String ModuleName { get { return "TestModule"; } }

    public void Dispose() {  }

    public void Init(HttpApplication app)
    {
        app.BeginRequest += (new EventHandler(this.DoBeginRequest));
    }

    private void DoBeginRequest(Object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        context.Response.Write("<pre>Request URL: " + context.Request.FilePath + "</pre>");
        context.Response.Flush();            
        System.Diagnostics.Debug.WriteLine(context.Request.ToString());
    }
}

它是这样加载的:

<system.webServer>
  <modules>
    <add name="TestModule" type="TestModule"/>
  </modules>
</system.webServer>

当我从Web浏览器或curl调用此函数时,Output选项卡中显示两行日志,并显示以下响应:

<pre>Request URL: /example</pre><pre>Request URL: /example</pre>

这表明每次都是相同的Context。为什么会发生这种情况?Request对象中有很多字段,但我在两次调用中无法发现它们之间的任何差异。是否有一些属性我应该检查,以提供一个"阶段",我应该只响应其中之一?
我在网站上找到了一些相关的问题,但大多数问题似乎倾向于Web浏览器寻找另一种资源,如favicon.ico,而这里的情况并非如此。
MSDNBeginRequest的细节上看起来有点轻,所以到目前为止我还没有找到很多帮助。
我可能错过了一些明显的东西,这是我第一次遇到。net/iis等,我通常是一个java开发人员。

    • 更新**:

我已经转储了Request的所有公共属性,这是两者之间的区别:

Headers == Accept=*%2f*&Host=localhost%3a2017&User-Agent=curl%2f7.35.0
Headers == Content-Length=0&Accept=*%2f*&Host=localhost%3a2017&User-Agent=curl%2f7.35.0

具体来说,Content-Length头是在第二次调用时设置的,这在curl请求中并不存在:

> GET /example HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:2017
> Accept: */*

这个IIS是不是想提供帮助?在处理完整个请求后,它知道请求主体的长度是(0),然后用这个集合再次调用它?

6pp0gazn

6pp0gazn1#

好吧,在经历了很多挫折之后,我发现一些特定的URL并没有遭受这种行为的困扰。带有“扩展名”的URL不会这样做:

curl http://localhost:2017/test
 > BeginRequest
 > BeginRequest 

curl http://localhost:2017/test.abc
 > BeginRequest

curl http://localhost:2017/.a
 > BeginRequest

通过在线挖掘,我发现了一个名为ExtensionlessUrl-Integrated-4.0的Handler的引用,它是由主配置文件applicationhost.config加载的。我真的不知道这是怎么回事,也不知道为什么它会导致请求重复,但在我自己的web.config中显式删除它解决了这个问题:

<system.webServer>
      <handlers>
        <remove name="ExtensionlessUrl-Integrated-4.0" />
      </handlers>
      <modules>
        <add name="TestModule" type="TestModule"/>
      </modules>
    </system.webServer>

我必须承认,我有点担心我以后可能会遇到的其他类似陷阱-applicationhost.config加载了 * 很多 * 其他处理程序和模块,其中任何一个都可能在我的模块能够得到它之前与这样的东西混淆。

tjvv9vkg

tjvv9vkg2#

使用LogRequest事件侦听器而不是BeginRequest应该可以满足您的需要:

public void Init(HttpApplication app)
{
    app.LogRequest += DoBeginRequest; // TODO: Rename your function
}

是的,我在非常干净的ASP.NET Web应用程序上看到了您的行为。它与favicon.ico附加请求无关。它可能与IIS可能在应用程序池中创建的多个应用程序示例有关。并且您的模块的多个示例具有对同一事件的多个订阅。它在这里的某个地方...但我现在无法在我的代码中证明这些理论。

sycxhyv7

sycxhyv73#

(Note:此解决方案可能不适用于所有应用)
只需在事件处理程序的末尾调用CompleteRequest()(可以是BeginRequest、PostAuthorizeRequest或其他内容)。
此调用完成请求处理并阻止其他处理程序工作,但是如果您已经处理了它,则很可能不会进行后处理,因此没有什么大不了的。

相关问题