Доступ к коллекции форм в IHttpModule приводит к тому, что обработчик событий не вызывается на странице по умолчанию - PullRequest
3 голосов
/ 18 марта 2011

Хорошо, это странно. Я создал простой пример сайта, чтобы продемонстрировать проблему. В ней у меня есть страница 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;
    }
}

Опять же, это всего лишь демонстрация, но суть в том, что я обращаюсь к запросу, чтобы получить значение из строки запроса. Если я запускаю это в Кассини, все работает нормально. Однако, когда я запускаю это в IIS, это то, что происходит. Когда я запускаю сайт по адресу:

http://mysamplesite.dev/

и затем нажмите на кнопку, ничего не происходит. Страница просто перезагружается, но мой обработчик события для кнопки никогда не вызывается, и впоследствии текст метки никогда не обновляется. Однако, если я тогда запусту его на:

http://mysamplesite.dev/Default.aspx

и затем нажмите кнопку, все работает нормально, и мой обработчик событий вызывается!

После копания я изменил код в модуле так:

string text = "queryStringParam";

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

Обратите внимание, здесь я обращаюсь к свойству QueryString напрямую, а не к контексту. Запрос. Когда я изменил его на это, он работает нормально, независимо от того, был ли у меня Default.aspx в URL?!

Следующий шаг, который я сделал, я посмотрел на 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;

И теперь он снова сломан! Короче говоря, просто получая доступ к коллекции Form по запросу в IHttpModule, я каким-то образом облажаю PostBack, и событие никогда не запускается.

У кого-нибудь есть идеи, почему это происходит? Я в большей степени парень из ASP.Net MVC, я не знаю ASP.Net и всех тех мелочей, которые он тянет за кулисами, достаточно хорошо, чтобы действительно понять, почему это происходит.

Ответы [ 2 ]

1 голос
/ 21 марта 2011

Когда делается запрос к "http://mysamplesite.dev/Default.aspx",, обработчик событий context_BeginRequest вызывается только один раз, как и следовало ожидать. Однако, когда запрос делается к" http://mysamplesite.dev/",, по какой-то причине context_BeginRequest вызывается дважды.

Для "http://mysamplesite.dev/"," первый проход через context_BeginRequest правильно загружает значения Form при выполнении context.Request["queryStringParam"], но второй проход - нет (Я проверил закрытое значение _form наcontext.Request с использованием отражения). За это время метод Page_Load для страницы вызывается только один раз.

Таким образом, событие не обрабатывается должным образом, поскольку ASP.NET обрабатывает запрос для "/"немного иначе, чем он обрабатывает запрос для "/Default.aspx", запуская BeginRequest для модуля дважды, а не один раз. Что касается того, почему ASP.NET делает это, я не совсем уверен. Вы, вероятно, вероятнонеобходимо профилировать запрос ASP.NET и посмотреть, какие методы вызываются в HttpRequest, чтобы понять, почему значения формы не передаются должным образом при втором вызове context_BeginRequest (и, кроме того, почему этот второй вызов даже выполняется впервое место).

Примечание: это должна быть внутренняя вещь ASP.NET (может быть Server.Transfer из "/" в "/Default.aspx" или что-то подобное), потому что Fiddler2 показывает только один приходящий запросиз браузера для "http://mysamplesite.dev/".

1 голос
/ 18 марта 2011
  1. дайте вашей кнопке ID (не повезло)
  2. попробуйте fiddler и посмотрите, как выглядит трафик - здесь происходит что-то смешное.
...