Хорошо, это может показаться немного запутанным и сложным, так что потерпите меня.
Мы написали структуру, которая позволяет нам определять удобные 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, что ужасно неэффективно.
Это подводит меня к собственному вопросу: сталкивался ли кто-нибудь когда-либо с этим, и есть ли у кого-нибудь какие-либо советы или знает ли кто-нибудь, что делать, чтобы все снова заработало? Пока что кто-то предлагал использовать собственный Модуль перезаписи URL от Microsoft. Помогло бы это решить нашу проблему?
Спасибо.





Просто предположите: обработчик, указанный в IIS7% windir% \ system32 \ inetsrv \ config \ applicationhost.config, который обрабатывает ваш запрос, вообще не позволяет глаголу POST пройти, и он оценивает это правило, прежде чем определить, не существует.
Поскольку IIS7 использует .net сверху вниз, использование HttpModule не приведет к снижению производительности. На самом деле существует несколько управляемых модулей HttpModule, которые всегда используются для каждого запроса. Когда запускается событие BeginRequest, возможно, SessionStateModule не был добавлен в коллекцию Modules, поэтому, если вы попытаетесь обработать запрос во время этого события, информация о состоянии сеанса не будет доступна. Установка свойства 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.
Спасибо за комментарий! Как только у меня будет возможность попробовать, я дам вам знать, сработало ли это.
Нет, извините, я нахожусь в середине крайнего срока :( Но я постараюсь обойти его в ближайшие несколько недель.
Стефан, см. Ответ Мартина ниже
В моем решении не используется поставщик 404 по умолчанию. Вы специально сказали, что используете свою собственную страницу 404, для которой требуется состояние сеанса. В этом случае вам нужно было бы сделать так, чтобы ваш обработчик реализовал IRequiresSessionState.
Мартин - мой коллега, поэтому он работает с той же проблемой, но спасибо, мы еще раз рассмотрим.
Да, я определенно рекомендую переписать URL (используя Microsoft IIS7, одну или одну из многих альтернатив). Это специально разработано для предоставления удобных URL-адресов, в то время как документы об ошибках являются последней опорой для сбоев, которые имеют тенденцию искажать входящие данные, поэтому они могут быть не такими, как вы ожидаете.
Microsoft выпустила исправление для этого:
http://support.microsoft.com/default.aspx/kb/956578
Похоже, это работает! Интересно, что Microsoft пришлось исправить, чтобы он заработал;) Спасибо!
Очевидно, эта загрузка больше не доступна для 32-битных процессоров, только для 64-битных. Странный. Кто-нибудь видел загрузку где-нибудь?
Проблема в IIS 7, связанная с тем, что пост-переменные не передаются пользовательским обработчикам ошибок, исправлена в пакете обновления 2 для Vista. Не пробовал на Windows Server, но уверен, что и там он будет исправлен.
HttpHandler установлен на verb = "*" (в web.config, а не в applicationHost.config). Я не думаю, что это должно вызвать какие-то проблемы, не так ли?