#c# #.net #iis-7 #httphandler
Вопрос:
Ладно, это может показаться немного запутанным и сложным, так что потерпите меня.
Мы написали структуру, которая позволяет нам определять дружественные URL-адреса. Если вы перейдете по любому произвольному URL-адресу, IIS попытается отобразить ошибку 404 (или, в некоторых случаях, 403;14 или 405). Однако IIS настроен таким образом, что все, что связано с этими конкретными ошибками, отправляется в файл .aspx. Это позволяет нам реализовать HttpHandler для обработки запроса и выполнения других действий, которые включают в себя поиск связанного шаблона и последующее выполнение всего, что с ним связано.
Теперь все это работает в IIS 5 и 6 и, в некоторой степени, в IIS7, но с одной оговоркой, которая возникает при отправке формы.
Видите ли, когда вы отправляете форму по несуществующему URL-адресу, IIS говорит «ах, но этот URL-адрес не существует» и выдает ошибку 405 «метод не разрешен». Поскольку мы просим IIS перенаправлять эти ошибки на нашу страницу .aspx и, следовательно, обрабатывать их с помощью нашего HttpHandler, обычно это не проблема. Но по состоянию на IIS7 вся информация о сообщениях пропала без вести после перенаправления на 405. И поэтому вы больше не можете делать самые тривиальные вещи, связанные с формами.
Чтобы решить эту проблему, мы попытались использовать HttpModule, который сохраняет данные POST, но, похоже, не инициализировал сеанс в нужное время (когда это необходимо). Мы также пытались использовать HttpModule для всех запросов, а не только для отсутствующих запросов, которые достигли 404/403;14/405, но это означает, что такие вещи, как изображения, css, js и т. Д., Обрабатываются кодом .NET, Что ужасно неэффективно.
Что подводит меня к актуальному вопросу: сталкивался ли кто-нибудь с этим когда-либо, и есть ли у кого-нибудь какие-либо советы или знания о том, что нужно сделать, чтобы все снова заработало? До сих пор кто-то предлагал использовать собственный модуль перезаписи URL-адресов Microsoft. Поможет ли это решить нашу проблему?
Спасибо.
Ответ №1:
Корпорация Майкрософт выпустила исправление для этого :
Комментарии:
1. Похоже, это работает! Интересно, что Microsoft пришлось исправить, чтобы запустить его 😉 Спасибо!
2. По-видимому, эта загрузка больше недоступна для 32-разрядных процессоров, только для 64-разрядных. Странный. Кто-нибудь видел загрузку в другом месте?
Ответ №2:
Поскольку IIS7 использует .net сверху вниз, при использовании HttpModule не будет никаких дополнительных затрат на производительность, фактически существует несколько управляемых HttpModules, которые всегда используются при каждом запросе. При запуске события BeginRequest модуль SessionStateModule, возможно, не был добавлен в коллекцию модулей, поэтому, если вы попытаетесь обработать запрос во время этого события, информация о состоянии сеанса будет недоступна. Настройка HttpContext.Свойство Handler инициализирует состояние сеанса, если оно требуется запрошенному обработчику, поэтому вы можете просто установить обработчик на свою страницу 404, которая реализует состояние irequiressession. Приведенный ниже код должен помочь, хотя вам, возможно, потребуется написать другую реализацию для метода 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)
amp;amp; System.IO.File.Exists(System.IO.Path.Combine(path, "default.aspx"))))
return true;
return false;
}
}
Изменить: я добавил реализацию IsMissing()
Примечание: В IIS7 модуль состояния сеанса по умолчанию не запускается глобально. Есть два варианта: включить модуль состояния сеанса для всех запросов (см. Мой комментарий выше о запуске управляемых модулей для всех типов запросов), или вы можете использовать отражение для доступа к внутренним участникам внутри System.Web.dll.
Комментарии:
1. Спасибо за комментарий! Как только у меня появится возможность попробовать, я дам вам знать, сработало ли это.
2. Нет, извините, у меня в разгаре крайний срок 🙁 Но я постараюсь сделать это в ближайшие несколько недель.
3. Стефан, смотри ответ Мартина ниже
4. В моем решении не используется поставщик 404 по умолчанию. Вы конкретно сказали, что используете свою собственную страницу 404, для которой требуется состояние сеанса. В этом случае вам нужно было бы сделать так, чтобы ваш обработчик реализовывал состояние irequiressession.
5. Мартин — мой коллега, так что он работает с той же проблемой, но спасибо, мы посмотрим еще раз.
Ответ №3:
Проблема в IIS 7, связанная с тем, что переменные post не передаются пользовательским обработчикам ошибок, исправлена в пакете обновления 2 для Vista. Не пробовал это на Windows Server, но я уверен, что там это тоже будет исправлено.
Ответ №4:
Просто предположение: обработчик, указанный в IIS7 %windir%system32inetsrvconfigapplicationhost.config, который обрабатывает ваш запрос, вообще не позволяет глаголу POST пройти, и он оценивает это правило, прежде чем определить, существует ли URL-адрес.
Комментарии:
1. Для HttpHandler установлено значение verb=»*» (в web.config, а не в applicationHost.config). Я не думаю, что это должно вызвать какие-либо проблемы, не так ли?
Ответ №5:
Да, я бы определенно рекомендовал переписать URL (используя Microsoft IIS7 или одну из многих альтернатив). Это специально разработано для предоставления удобных URL-адресов, в то время как документы об ошибках являются последним средством защиты от сбоев, что приводит к накоплению входящих данных, поэтому они могут оказаться не такими, как вы ожидаете.