So yesterday I posted about the big big big problem of webparts framework
Personalization.ToggleScope()
method which will issue a
Server.Transfer()
call and that will make it incompatible with ASP.NET routing because when page has been routed (that is, it doesn't exist) that Server.Transfer() call will end up in error because (guess!) file doesn't exist. Googling around Web, I found that problem to be common for MVC framework and some code has been posted to emulate it. So my first attempt was to try to get around that problem by using
Server.TransferRequest(url,false)
since that method, only available on IIS7, should process the whole IIS pipeline instead of skipping it the way Server.Transfer() does and I thought that could be useful to include URLRoutingModule into chain and thus having my routed file back to life. No luck: same file does not exist error. I was already subclassing WebpartManager and WebpartPersonalization classes in order to provide my own logic there and I thought to replace protected
Personalization.TransferToPage()
method in order to replace Server.Transfer logic to something else, Server.TransferRequest for example. So I came up with one of those solutions for MVC somewhere on the Internet and implemented this:
Private Shadows Sub TransferToCurrentPage(ByVal page As Page)
Dim request As HttpRequest = page.Request
If request Is Nothing Then
Throw New InvalidOperationException("WebPartManager.Page.Request Cannot Be Null")
End If
Dim url As String = request.CurrentExecutionFilePath
If page.Form Is Nothing OrElse String.Equals(page.Form.Method, "post", StringComparison.OrdinalIgnoreCase) Then
Dim queryString As String = page.ClientQueryString
If Not String.IsNullOrEmpty(queryString) Then
url = String.Concat(url, "?", queryString)
End If
End If
Dim scriptManager As ScriptManager = System.Web.UI.ScriptManager.GetCurrent(page)
If Not scriptManager Is Nothing AndAlso scriptManager.IsInAsyncPostBack Then
page.Response.Redirect(url)
Else
'page.Server.TransferRequest(url, False)
If HttpContext.Current.Items("Post!") Is Nothing OrElse HttpContext.Current.Items("Post!") <> True Then
' Adapted from : http://forums.asp.net/p/1458709/3347077.aspx
HttpContext.Current.RewritePath(url)
Dim context As HttpContextBase = New HttpContextWrapper(HttpContext.Current)
Dim routeData As RouteData = RouteTable.Routes.GetRouteData(context)
If routeData IsNot Nothing Then
Dim routeHandler As IRouteHandler = routeData.RouteHandler
If routeHandler IsNot Nothing Then
Dim requestContext As RequestContext = New RequestContext(context, routeData)
Dim httpHandler As IHttpHandler = routeHandler.GetHttpHandler(requestContext)
If httpHandler IsNot Nothing Then
HttpContext.Current.Items("Post!") = True
httpHandler.ProcessRequest(HttpContext.Current)
End If
End If
End If
End If
End If
End Sub
Ugly Post! references in Context.Items were just a quick way to avoid infinite loops when calling the same page, which is always the case for ToggleScope(). This probably causes problems with postback logic because after click on a button to trigger scope change, scope doesn't change and, if left without any control, that ProcessRequest call will simply trigger an infinite loop of calling back itself again and again. Even when I stop that loop and take care to only run ProcessRequest a single time, postback won't occurr and scope won't be changed, though everything else keeps working.
Then I tried to work on a different basis, leaving Server.Transfer() call in place and working on that specific file does not exist error. By using a custom VirtualPathProvider, I could return true to calls from ASP.NET over specific files and that would get rid of that error but, unfortunately, URLRoutingModule doesn't come into action if file exists so that's not an option. Then I tried to set module to route existing files too and I'm trying to provide and implementation so my VirtualPathProvider will return contents from default.aspx to such requests: let's see what happens but this will be my last attempt before dropping v4.0 and start over to v4.2, getting rid of Webparts framework.