3

好吧,这很奇怪。我创建了一个简单的示例站点来演示该问题。在其中,我有一个 Default.aspx 页面,上面有一个按钮:

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <p><asp:Button OnClick="ButtonClick" Text="Button" runat="server" />
    </p>
    <asp:Label ID="output" runat="server" />
</asp:Content>

后面的代码只是在按钮单击时设置标签文本:

    protected void ButtonClick(object sender, EventArgs e)
    {
        output.Text = "Button Click!!";
    }

然后我有一个 IHttpModule 会为每个请求调用:

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

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

    private void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = sender as HttpApplication;
        if(application == null)
        {
            return;
        }
        HttpContext context = application.Context;
        if(context == null)
        {
            return;
        }

        string text = "queryStringParam";

        var value = context.Request[text];
        var boolValue = value == null;
    }
}

同样,这只是一个演示,但这里的重点是,我正在访问请求,以从查询字符串中获取值。如果我在 Cassini 中运行它,一切正常。但是,当我在 IIS 中运行它时,会发生这种情况。当我在以下位置运行网站时:

http://mysamplesite.dev/

然后单击按钮,没有任何反应。页面只是重新加载,但我的按钮事件处理程序永远不会被调用,随后标签文本永远不会更新。但是,如果我然后在以下位置运行它:

http://mysamplesite.dev/Default.aspx

然后单击按钮,它工作正常,我的事件处理程序确实被调用了!

在挖掘了一些之后,我将模块中的代码更改为:

string text = "queryStringParam";

var value = context.Request.QueryString[text];
var boolValue = value == null;

注意,这里我直接访问 QueryString 属性,而不是访问 context.Request。当我将其更改为此时,无论我在 url 中是否有 Default.aspx,它都可以正常工作?!

我做的下一步是,我查看了 Reflector 以了解 HttpRequest 索引器属性的代码实际上做了什么:

public string this[string key]
{
    get
    {
        string str = this.QueryString[key];
        if (str != null)
        {
            return str;
        }
        str = this.Form[key];
        if (str != null)
        {
            return str;
        }
        HttpCookie cookie = this.Cookies[key];
        if (cookie != null)
        {
            return cookie.Value;
        }
        str = this.ServerVariables[key];
        if (str != null)
        {
            return str;
        }
        return null;
    }
}

看起来很无害,它只是为我检查各种集合,所以我不需要单独检查每个集合。那么我想知道,其中哪一个电话打破了它。然后我将我的模块更改为:

string text = "queryStringParam";

var value = context.Request.QueryString[text];
var boolValue = value == null;

var value2 = context.Request.Form[text];
var boolValue2 = value2 == null;

而现在又坏了!因此,长话短说,仅通过访问IHttpModule 中请求的 Form 集合,我以某种方式搞砸了 PostBack,并且该事件永远不会被触发。

有谁知道为什么会这样?我更像是一个 ASP.Net MVC 人,我不了解 ASP.Net 以及它在幕后拉动的所有花絮,足以真正了解为什么会发生这种情况。

4

2 回答 2

1
  1. 给你的按钮一个 ID(不走运)
  2. 试试 fiddler,看看交通是什么样子的——这里发生了一些有趣的事情。
于 2011-03-18T18:24:34.810 回答
1

当向“http://mysamplesite.dev/Default.aspx”发出请求时,context_BeginRequest事件处理程序只被调用一次,正如您所期望的那样。但是,当向“http://mysamplesite.dev/”发出请求时,由于某种原因context_BeginRequest被调用了两次。

对于“http://mysamplesite.dev/”,第一次通过在执行时正确context_BeginRequest加载值,但第二次通过没有(我检查了使用反射的私有值)。在此期间,页面的方法只被调用一次。Formcontext.Request["queryStringParam"]_formcontext.RequestPage_Load

因此,该事件没有得到正确处理,因为 ASP.NET 处理“/”请求与处理“/Default.aspx”请求略有不同,通过触发BeginRequest模块两次而不是一次。至于为什么 ASP.NET 这样做,我不太确定。您可能需要分析 ASP.NET 请求并查看调用了哪些方法,HttpRequest以查看为什么第二次调用时表单值没有正确传递context_BeginRequest(以及为什么甚至首先进行第二次调用) )。

注意:这必须是一个内部 ASP.NET 的东西(可能是从“/”到“/Default.aspx”的 Server.Transfer 或类似的东西),因为 Fiddler2 只显示来自浏览器的一个请求“http://mysamplesite” .dev/”。

于 2011-03-21T06:26:01.520 回答