Публикация форм на 404+ HttpHandler в IIS7: почему пропали все данные POST? - PullRequest
2 голосов
/ 19 сентября 2008

ОК, это может показаться немного запутанным и сложным, так что терпите меня.

Мы написали структуру, которая позволяет нам определять дружественные URL-адреса. Если вы переходите по любому произвольному URL-адресу, IIS пытается отобразить ошибку 404 (или, в некоторых случаях, 403; 14 или 405). Однако IIS настроен так, что все, что связано с этими конкретными ошибками, отправляется в файл .aspx. Это позволяет нам реализовать HttpHandler для обработки запроса и выполнения чего-либо, что включает в себя поиск связанного шаблона и последующее выполнение всего, что с ним связано.

Теперь, это все работает в IIS 5 и 6 и, в некоторой степени, в IIS7 - но для одного улова, который происходит, когда вы публикуете форму.

Смотрите, когда вы публикуете форму на несуществующий URL, IIS говорит "ах, но этот URL не существует" и выдает ошибку 405 "метод не разрешен". Поскольку мы говорим IIS перенаправить эти ошибки на нашу страницу .aspx и, следовательно, обрабатывать их с помощью нашего HttpHandler, обычно это не проблема. Но с IIS7 вся информация POST пропала после перенаправления на 405. И поэтому вы больше не можете делать самые тривиальные вещи, связанные с формами.

Чтобы решить эту проблему, мы попытались использовать HttpModule, который сохраняет данные POST, но, по-видимому, не имеет инициализированного сеанса в нужное время (когда это необходимо). Мы также попытались использовать HttpModule для всех запросов, не только отсутствующие запросы, которые достигли 404/403; 14/405, но это означает, что такие вещи, как изображения, CSS, JS и т. Д. Обрабатываются .NET-кодом, что ужасно неэффективно. 1009 *

Что подводит меня к актуальному вопросу: кто-нибудь когда-либо сталкивался с этим, и есть ли у кого-нибудь совет или знать, что делать, чтобы все снова заработало? До сих пор кто-то предлагал использовать собственный модуль перезаписи URL-адреса Microsoft . Поможет ли это решить нашу проблему?

Спасибо.

Ответы [ 5 ]

2 голосов
/ 20 октября 2009

Проблема в IIS 7 пост-переменных, не передаваемых пользовательским обработчикам ошибок, исправлена ​​в пакете обновления 2 для Vista. Не пробовал на Windows Server, но я уверен, что это тоже будет исправлено.

2 голосов
/ 08 января 2009

Microsoft выпустила исправление для этого:

http://support.microsoft.com/default.aspx/kb/956578

2 голосов
/ 21 сентября 2008

Поскольку IIS7 использует .net сверху вниз, при использовании HttpModule не возникнет никаких проблем с производительностью. Фактически существует несколько управляемых HttpModule, которые всегда используются при каждом запросе. Когда происходит событие BeginRequest, модуль SessionStateModule может не быть добавлен в коллекцию модулей, поэтому, если вы попытаетесь обработать запрос во время этого события, информация о состоянии сеанса будет недоступна. Установка свойства HttpContext.Handler инициализирует состояние сеанса, если запрошенный обработчик нуждается в этом, поэтому вы можете просто установить обработчик на свою причудливую страницу 404, которая реализует IRequiresSessionState. Приведенный ниже код должен помочь, хотя вам может потребоваться написать другую реализацию для метода IsMissing ():

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;
    }
}

Редактировать: я добавил реализацию IsMissing ()

Примечание. В IIS7 модуль состояния сеанса не запускается глобально по умолчанию. Есть два варианта: включить модуль состояния сеанса для всех запросов (см. Мой комментарий выше о запуске управляемых модулей для всех типов запросов) или использовать отражение для доступа к внутренним элементам внутри System.Web.dll.

0 голосов
/ 20 октября 2008

Да, я бы определенно рекомендовал переписать URL (используя Microsoft IIS7, один или один из множества вариантов). Это специально разработано для предоставления удобных URL-адресов, тогда как документы об ошибках являются последней защитой при сбоях, которая имеет тенденцию портить входящие данные, поэтому они могут не соответствовать вашим ожиданиям.

0 голосов
/ 19 сентября 2008

Просто предположение: обработчик, указанный в IIS7% windir% \ system32 \ inetsrv \ config \ applicationhost.config, который обрабатывает ваш запрос, вообще не позволяет глаголу POST пройти, и он оценивает это правило, прежде чем определить если URL не существует.

...