То, что я пытаюсь сделать, в принципе простое, но жизненный цикл страниц ASP.NET выливает на мой день ведро холодной воды.
Вот проблема
Мы реализовали перенаправление URL-адресов, и я унаследовал код, который читается следующим образом в Global.ASAX в Sub Application_BeginRequest:
dv.Table = CommonFunctions.ConvertXmlFileToDataSet("/XmlData/WebAppFolders.xml").Tables("Application")
dv.RowFilter = "'" + fullOrigionalPath + "' LIKE '%'+ folder + '%'"
If dv.Count > 0 Then 'match on key to redirect
If fullOrigionalPath.EndsWith(dv(0)("folder") + "/") Then
Context.RewritePath(dv(0)("basePage"), True)
Else 'missing page in directory --> redirect
HttpContext.Current.Items("Raise404") = "true"
Response.Redirect("/" + dv(0)("folder"))
End If
Return
End If
По сути, мы читаем большой файл XML, содержащий перенаправления URL. Это работает нормально. Проблема возникает в линии...
HttpContext.Current.Items("Raise404") = "истина"
В контексте Application_BeginRequest объект сеанса еще недоступен, поэтому я не мог использовать его для хранения флага, который я назвал Raise404. Вместо этого мне пришлось прибегнуть к использованию коллекции Items.
Проблема возникает, когда происходит перенаправление. Жизненный цикл новой страницы уничтожает массив Items и перезаписывает его новым пустым.
К тому времени, когда я пытаюсь использовать свой флаг Raise404, его уже нет в событии PreRender моей страницы.
Чтобы усложнить ситуацию, мы используем мастер-страницы, поэтому меня попросили разместить код, который мы хотим выполнить, на мастер-странице.
В идеале, если бы массив Items не уничтожался, этот код работал бы:
Private Sub Page_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
If HttpContext.Current.Items("Raise404") IsNot Nothing AndAlso HttpContext.Current.Items("Raise404").Equals("true") Then
Response.StatusCode = 404
HttpContext.Current.Items("Raise404") = Nothing
End If
End Sub
Я не уверен, какую переменную я мог бы использовать для хранения своего флага и позволить ему пережить перенаправление.
Любые идеи?
Обновление: проблема заключается в том, что обработчиком HTTP, обслуживающим мой запрос, является System.Web.DefaultHTTPHandler, который не реализует IRequiresSessionState, поэтому, когда мой запрос обрабатывается внутри Global ASAX, сеанс не создается. Итак, кажется, что решение будет состоять в том, чтобы написать собственный HTTPHandler, который реализует IRequiresSessionState, и использовать его для всех моих файлов .aspx. Даже в этом случае состояние сеанса не создается в Global.ASAX до тех пор, пока не будет поднят PreRequestHandlerExecute. Итак, собирая все это вместе, я думаю, мне нужно написать собственный обработчик HTTP, который реализует IRequiresSessionState, и отложить перенаправление страницы до тех пор, пока не будет поднят PreRequestHandlerExecute, где я смогу сохранить свой флаг в состоянии сеанса, и только после этого, перенаправить мою страницу.
Не очень элегантно, и мне интересно, будут ли какие-либо последствия для производительности.