我创建了一个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
,而这里的情况并非如此。
MSDN在BeginRequest
的细节上看起来有点轻,所以到目前为止我还没有找到很多帮助。
我可能错过了一些明显的东西,这是我第一次遇到。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),然后用这个集合再次调用它?
3条答案
按热度按时间6pp0gazn1#
好吧,在经历了很多挫折之后,我发现一些特定的URL并没有遭受这种行为的困扰。带有“扩展名”的URL不会这样做:
通过在线挖掘,我发现了一个名为
ExtensionlessUrl-Integrated-4.0
的Handler的引用,它是由主配置文件applicationhost.config
加载的。我真的不知道这是怎么回事,也不知道为什么它会导致请求重复,但在我自己的web.config
中显式删除它解决了这个问题:我必须承认,我有点担心我以后可能会遇到的其他类似陷阱-
applicationhost.config
加载了 * 很多 * 其他处理程序和模块,其中任何一个都可能在我的模块能够得到它之前与这样的东西混淆。tjvv9vkg2#
使用LogRequest事件侦听器而不是BeginRequest应该可以满足您的需要:
是的,我在非常干净的ASP.NET Web应用程序上看到了您的行为。它与
favicon.ico
附加请求无关。它可能与IIS可能在应用程序池中创建的多个应用程序示例有关。并且您的模块的多个示例具有对同一事件的多个订阅。它在这里的某个地方...但我现在无法在我的代码中证明这些理论。sycxhyv73#
(Note:此解决方案可能不适用于所有应用)
只需在事件处理程序的末尾调用CompleteRequest()(可以是BeginRequest、PostAuthorizeRequest或其他内容)。
此调用完成请求处理并阻止其他处理程序工作,但是如果您已经处理了它,则很可能不会进行后处理,因此没有什么大不了的。