C# 将表格发布到404+;IIS7中的HttpHandler:为什么所有POST数据都丢失了?

C# 将表格发布到404+;IIS7中的HttpHandler:为什么所有POST数据都丢失了?,c#,.net,iis-7,httphandler,C#,.net,Iis 7,Httphandler,好吧,这听起来可能有点混乱和复杂,所以请耐心听我说 我们已经编写了一个框架,允许我们定义友好的URL。如果您浏览任意URL,IIS将尝试显示404错误(或者在某些情况下显示403;14或405)。但是,设置IIS是为了将指向这些特定错误的任何内容发送到.aspx文件。这使我们能够实现一个HttpHandler来处理请求并完成一些工作,其中包括查找相关模板,然后执行与之相关的任何内容 现在,这些都可以在IIS5和IIS6中使用,在某种程度上,也可以在IIS7中使用——但是有一个问题,当你发布表单时

好吧,这听起来可能有点混乱和复杂,所以请耐心听我说

我们已经编写了一个框架,允许我们定义友好的URL。如果您浏览任意URL,IIS将尝试显示404错误(或者在某些情况下显示403;14或405)。但是,设置IIS是为了将指向这些特定错误的任何内容发送到.aspx文件。这使我们能够实现一个HttpHandler来处理请求并完成一些工作,其中包括查找相关模板,然后执行与之相关的任何内容

现在,这些都可以在IIS5和IIS6中使用,在某种程度上,也可以在IIS7中使用——但是有一个问题,当你发布表单时就会发生

请看,当您将表单发布到不存在的URL时,IIS会说“啊,但该URL不存在”,并抛出405“方法不允许”错误。因为我们告诉IIS将这些错误重定向到我们的.aspx页面,并因此使用我们的HttpHandler处理它,所以这通常不是问题。但是从IIS7开始,所有的POST信息在被重定向到405后都丢失了。因此,你不能再做涉及形式的最琐碎的事情了

为了解决这个问题,我们尝试使用HttpModule,它保留POST数据,但在正确的时间(需要时)似乎没有初始化会话。我们还尝试对所有请求使用HttpModule,而不仅仅是命中404/403的丢失请求;14/405,但这意味着像图像、css、js之类的东西正在由.NET代码处理,这是非常低效的

这让我想到了一个实际问题:有没有人遇到过这种情况,有没有人有什么建议或知道如何让事情恢复正常?到目前为止,有人建议使用微软自己的。这有助于解决我们的问题吗


谢谢。

只是猜测一下:IIS7的%windir%\system32\inetsrv\config\applicationhost.config中指定的处理程序正在处理您的请求,它根本不允许POST谓词通过,在确定URL是否不存在之前,它正在评估该规则。

由于IIS7自上而下使用.net,因此使用HttpModule不会产生任何性能开销,事实上,在每个请求上都会使用多个托管HttpModule。触发BeginRequest事件时,SessionStateModule可能尚未添加到Modules集合中,因此,如果您尝试在此事件期间处理请求,则没有可用的会话状态信息。如果请求的处理程序需要,设置HttpContext.Handler属性将初始化会话状态,因此您可以将处理程序设置为实现IRequiresessionState的404页面。下面的代码应该可以做到这一点,不过您可能需要为IsMissing()方法编写不同的实现:

编辑:我添加了IsMissing()的一个实现


注意:在IIS7上,会话状态模块默认情况下不会全局运行。有两个选项:为所有请求启用会话状态模块(请参阅我上面关于为所有请求类型运行托管模块的评论),或者您可以使用反射来访问System.Web.dll中的内部成员。

是的,我绝对建议您重新编写URL(使用Microsoft的IIS7或众多备选方案之一)。这是专门为提供友好的URL而设计的,而错误文档是失败的最后一道防线,它往往会吞噬传入的数据,因此它可能不是您所期望的。Microsoft为此发布了一个修补程序:


IIS 7中的post变量未传递到自定义错误处理程序的问题已在service pack 2 for Vista中修复。还没有在Windows服务器上尝试过,但我相信它也会在那里得到修复

HttpHandler设置为verb=“*”(在web.config中,而不是applicationHost.config中)。我不认为这会引起任何问题,是吗?谢谢你的评论!一旦我有机会尝试,我会告诉你,如果它工作。不,对不起,我在最后期限的中间:(但我会在接下来的几周内尝试解决这个问题。Stefan,请参见下面Martin的回答。我的解决方案不使用默认的404提供程序。您明确说过您使用自己的404页面,需要会话状态。在这种情况下,您需要让您的处理程序实现iRequiresessionState。Martin是我的同事,所以他It’我们正在处理同一个问题,但谢谢,我们将再看一看。它看起来很有效!我想知道Microsoft必须修复什么才能使其启动并运行;)谢谢!显然,此下载不再适用于32位处理器,仅适用于64位。奇怪。有人在别处看到过此下载吗?
using System.Web;
using System.Web.UI;

class Smart404Module : IHttpModule
{
    public void Dispose() {}

    public void Init(HttpApplication context)
    {
        context.BeginRequest += new System.EventHandler(DoMapping);
    }

    void DoMapping(object sender, System.EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;

        if (IsMissing(app.Context))
            app.Context.Handler = PageParser.GetCompiledPageInstance(
                "~/404.aspx", app.Request.MapPath("~/404.aspx"), app.Context);
    }

    bool IsMissing(HttpContext context)
    {
        string path = context.Request.MapPath(context.Request.Url.AbsolutePath);

        if (System.IO.File.Exists(path) || (System.IO.Directory.Exists(path)
            && System.IO.File.Exists(System.IO.Path.Combine(path, "default.aspx"))))
            return true;
        return false;
    }
}