What I am trying to do is simple in principle, but the lifecycle of ASP.NET pages is throwing a bucket of cold water into my day.
Here is the problem
We have implemented URL Redirection and I've inherited code that reads like this in Global.ASAX, on 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
Basically we are reading a large XML file that contains the URL redirects. That's working fine. The problem happens in the line...
HttpContext.Current.Items("Raise404") = "true"
In the context of Application_BeginRequest, the session object is not yet available, so I could not use it to store a flag which I named Raise404. Instead I had to resort to using the Items collection.
The problem occurs when the redirect takes place. The new page lifecycle destroys the Items array and overwrites it with a new empty one.
By the time I try to use my flag Raise404, it no longer exists on my page PreRender event.
To complicate matters we use master pages, and so I was asked to place the code that we want to execute in the master page
Ideally, if the Items array wasn't being destroyed, this code would work:
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
I am not sure what kind of variable I could use to store my flag and allow it to survive the redirect.
Any ideas?
Update: The problem is that the HTTP Handler servicing my request is System.Web.DefaultHTTPHandler, which does not implement IRequiresSessionState, and so when my request is being handled inside Global ASAX there is no session created. So, it seems like the solution will be to write a custom HTTPHandler that implements IRequiresSessionState, and use that for all my .aspx files. Even then, a session state is not created in Global.ASAX until PreRequestHandlerExecute is raised. So, putting it all together I think I need to write a custom HTTP Handler that implements IRequiresSessionState, and delay the redirection of the page until PreRequestHandlerExecute is raised where I will be able to store my flag into the Session state, and only after that, redirect my page.
Not very elegant, and I wonder if there will be any performance implications.