2008-12-09 10 views
10

Я использую Context.RewritePath() в приложении ASP.NET 3.5, запущенном на IIS7.Файлы журнала IIS7, RewritePath и IIS

Я делаю это в приложении BeginRequest событие и все работает файл.

Запросы/спорт правильно переписаны по умолчанию .aspx? Id = 1 и т. Д.

Проблема в том, что в моем журнале IIS я вижу запросы GET для /Default.aspx?id=1, а не для/sports.

Этот вид кода отлично работал под IIS6.

Использование Microsoft Rewrite не является вариантом из-за некоторой бизнес-логики, которая должна быть реализована.

Спасибо.

EDIT:

Кажется, мой обработчик слишком рано в трубопроводе, но если перенести логику позднего события, чем вся переписана вещь не работает (это слишком поздно, StaticFileHandler поднимает мой запрос).

Я googled и googled, спросил вокруг, не могу поверить, что никто не имеет этой проблемы?

EDIT:

Yikes! Вот что я нашел на форуме IIS:

«Это связано с тем, что в интегрированном режиме IIS и asp.net совместно используют общий конвейер, а RewritePath теперь рассматривается IIS, а в IIS6 его даже не видел IIS - вы можете обойти это, используя классический режим, который будет вести себя как IIS6 ».

Окончательное обновление: Пожалуйста, взгляните на my answer below. Я обновил его результатами после более чем года в производственной среде.

+0

Muerte, правильный способ сделать это - ответить на ваш собственный вопрос. Вы заявили, что этот вопрос может быть правильным, поставив IIS 7 в классический режим, который будет работать так же, как IIS 6. До тех пор, пока вы понимаете, что вы не выиграете от повышения безопасности или производительности в новом IIS 7, сделав это, это кажется разумным ответом. – Spence 2009-02-17 12:47:29

+0

Я понимаю, что я могу ответить на свой вопрос, но я не считаю это ответом вообще, и я все еще преследую квест. :) Я кое-что пробовал, и я обязательно добавлю свой результат либо в качестве ответа, либо в качестве окончательного редактирования моего вопроса. – muerte 2009-02-17 15:50:19

+0

Я бы (и имел) просто посмотрю на сборку System.Web.Routing через Reflector. Чтобы узнать, где его подключить. IIRC, вам нужно сделать это в PostMapRequestHandler и PostAcquireRequestState. – leppie 2009-02-12 11:50:32

ответ

6

После некоторых исследований я, наконец, нашел решение проблемы.

Я заменил вызовы на метод Context.RewritePath() с новым (представленным в ASP.NET 3.5) Context.Server.TransferRequest() метод.

Это кажется очевидным сейчас, но не событие. Старший инженер Dev в команде IIS Core подумал об этом.

Я протестировал его для сеанса, проверки подлинности, обратной передачи, запроса, ... проблем и не нашел.

Tommorow Я развожу это изменение на сайт с очень высоким трафиком, и мы скоро узнаем, как это работает. :)

Я вернусь с обновлением.

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

Окончательное обновление: У меня есть это решение в производстве более года, и оно оказалось хорошим и стабильным решением без проблем.

4

После обработки запроса вы можете установить путь к исходному значению, но до того, как модуль протоколирования IIS записывает запись журнала.

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

public class RewriteModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.BeginRequest += OnBeginRequest; 
     context.EndRequest += OnEndRequest; 
    } 

    static void OnBeginRequest(object sender, EventArgs e) 
    { 
     var app = (HttpApplication)sender; 
     app.Context.Items["OriginalPath"] = app.Context.Request.Path; 
     app.Context.RewritePath("Default.aspx?id=1"); 
    } 

    static void OnEndRequest(object sender, EventArgs e) 
    { 
     var app = (HttpApplication)sender; 
     var originalPath = app.Context.Items["OriginalPath"] as string; 
     if (originalPath != null) 
     { 
      app.Context.RewritePath(originalPath); 
     } 
    } 

    public void Dispose() 
    { 

    } 
} 
2

У меня была точно такая же проблема. Один из способов - использовать Server.Transfer вместо Context.RewritePath. Server.Transfer не перезапускает весь жизненный цикл страницы, поэтому исходный URL-адрес все равно будет регистрироваться. Обязательно передайте «true» для параметра «preserveForm», чтобы коллекции QueryString и Form были доступны на второй странице.

0

Старый вопрос, но я обнаружил, что я не встретил вашу проблему, когда я сделал следующее:

а) Правило переписывания в web.config, чтобы направлять все запросы на /default.aspx, например:

<rule name="all" patternSyntax="Wildcard" stopProcessing="true"> 
     <match url="*"/> 
     <action type="Rewrite" url="/default.aspx"/> 
    </rule> 

b) Вызывается RewritePath в событии default.aspx Page_PreInit, чтобы переписать URL-адрес и строку запроса как то, что было передано в запросе (то есть местоположение, которое не существует).

Например, я запрашиваю «/ somepage /? X = y» (которого не существует).

а) правило Web.config отображает его /default.aspx

б) Page_PreInit переписывает его обратно "/ somepage /? Х = у".

В результате этого в IIS 7 (Экспресс и производство) журнал журнала отражает «/ somepage» для заглушки и «x = y» для запроса, а все свойства объекта «Запрос» отражают запрошенные (не- существующий) URL (это то, что я хотел).

Единственный странный эффект - в IIS Express элемент журнала записывается дважды. Однако этого не происходит в производстве (Windows Server 2008 R2).