2013-09-27 67 views
0

我正在使用ASP.NET 4.0路由,並正在從數據庫中讀取路由信息並添加如下的路由。簡而言之,我的自定義對象「RouteLookup」包含路由信息,包括可能或不可能被重定向到的另一個RouteLookup的ID。這裏的兩位RouteLookup條目在DB的例子:爲什麼RedirectToRoutePermanent爲查詢字符串添加「count = 0」?

RouteLookupID RouteName  RelativePath RequestHandler RouteHandler IsSecure RedirectedToRoute 
    13    PrivacyRoute about/privacy privacy.aspx NULL    0    0 
    14    PrivacyRoute1 privacy   privacy.aspx NULL    0    13  

RouteLookupID 14需要被永久重定向到RouteLookupID 13.我對跑起來的問題遺留下來的路線是,當我要求「http://mydomain.com/privacy」從瀏覽器並觀看Fiddler結果,它實際上重定向了TWICE並添加了「count = 0」作爲查詢字符串參數!我沒有IDEA,這個參數來自於我沒有進程,httphandler,等明確添加。

這裏發生了什麼事?任何想法都非常感謝,其餘的相關代碼如下。

我有一個繼承自Route的類,BaseRoute,所以我可以傳遞我自定義的RouteLookup對象以及在我命名爲BaseRouteHandler的自定義RouteHandler中進行檢查。

Public Class PageRouter 

Private Shared db As New QADBDataContext 

''''''' Is called from Global Application_Start 
Public Shared Sub MapRoutes(routeColl As RouteCollection) 

    Dim routeLookups As IEnumerable(Of RouteLookup) = From rt In db.RouteLookups Select rt 

    For Each rtLookUp As RouteLookup In routeLookups 
     Dim parameterizedURL As String = BuildParameterizedVirtualPath(rtLookUp) 

      ' Determine handler and route values 
      If rtLookUp.RouteHandler Is Nothing Then 
       RouteTable.Routes.Add(rtLookUp.RouteName, New BaseRoute(parameterizedURL, New BaseRouteHandler(), rtLookUp)) 
      Else 
       RouteTable.Routes.Add(rtLookUp.RouteName, New BaseRoute(parameterizedURL, Activator.CreateInstance(Type.GetType("QA." + rtLookUp.RouteHandler)), rtLookUp)) 
      End If    
    Next 
End Sub 

Protected Shared Function BuildParameterizedVirtualPath(rtLookUp As RouteLookup) As String 

    Dim parameterizedURL As String = rtLookUp.RelativePath 
    For Each param As RouteParameter In rtLookUp.RouteParameters 
     parameterizedURL &= "/{" + param.Name + "}" 
    Next 
    Return parameterizedURL 

End Function 

Public Shared Sub RedirectToRoutePermanent(rtData As RouteData) 

    Dim route As BaseRoute = DirectCast(rtData.Route, BaseRoute) 
    Dim rtLookup As RouteLookup = route.RouteLookup 
    Dim newRtLookupID As Integer = rtLookup.RedirectedToRoute 
    Dim newRtLookup As RouteLookup = (From rt In db.RouteLookups Where rt.RouteLookupID = newRtLookupID).SingleOrDefault 
    HttpContext.Current.Response.RedirectToRoutePermanent(newRtLookup.RouteName, rtData.Values.Values) 

End Sub 
End Class 

自定義路由類:

Public Class BaseRoute 
Inherits Route 

Private _routeLookup As RouteLookup = Nothing 

Public Sub New(url As String, routeHandler As IRouteHandler, routeLookup As RouteLookup) 
    MyBase.New(url, routeHandler) 
    _routeLookup = routeLookup 

End Sub 

Public ReadOnly Property RouteLookup As RouteLookup 
    Get 
     Return _routeLookup 
    End Get 
End Property 
End Class 

定製RouteHandler:

Public Class BaseRouteHandler 
Implements IRouteHandler 

Protected _baseRoute As BaseRoute = Nothing 
Protected _rtLookup As RouteLookup = Nothing 

Protected Overridable Sub InitializeContext(ByVal requestContext As System.Web.Routing.RequestContext) 

    _baseRoute = DirectCast(requestContext.RouteData.Route, BaseRoute) 
    _rtLookup = _baseRoute.RouteLookup 

End Sub 


Public Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) _ 
         As System.Web.IHttpHandler Implements System.Web.Routing.IRouteHandler.GetHttpHandler 

    InitializeContext(requestContext) 
    EnforceURLStandard(requestContext) 
    PerformRedirectIfNeeded(requestContext) 
    Return GetPageHandler(requestContext) 

End Function 


Protected Overridable Sub PerformRedirectIfNeeded(ByVal requestContext As System.Web.Routing.RequestContext) 

    If _rtLookup.RedirectedToRoute > 0 Then 
     PageRouter.RedirectToRoutePermanent(requestContext.RouteData) 
    End If 

End Sub 


Protected Sub EnforceURLStandard(ByVal requestContext As System.Web.Routing.RequestContext) 

    ' Test for: 
    ' * Proper protocol 
    ' * www. exists 
    ' * must be all lowercase 

    Dim scheme As String = HttpContext.Current.Request.Url.GetComponents(UriComponents.Scheme, UriFormat.UriEscaped) 
    Dim rightSide As String = HttpContext.Current.Request.Url.GetComponents(UriComponents.HostAndPort Or UriComponents.PathAndQuery, UriFormat.UriEscaped) 
    Dim newURL As String = Nothing 

    If Not rightSide.ToLower().StartsWith("www.") AndAlso Not rightSide.ToLower().StartsWith("localhost") _ 
     AndAlso Not rightSide.ToLower().StartsWith("uat") AndAlso Not rightSide.ToLower().StartsWith("ux") Then 
     newURL = scheme & "://www." & rightSide 
    End If 

    If _rtLookup.IsSecure <> requestContext.HttpContext.Request.IsSecureConnection Then 
     Dim newScheme As String = If(_rtLookup.IsSecure, "https", "http") 
     newURL = newScheme & rightSide 
    End If 

    Dim pattern As String = "[A-Z]" 
    If Not String.IsNullOrWhiteSpace(newURL) Then 
     If Regex.IsMatch(newURL, pattern) Then 
      newURL = newURL.ToLower() 
     End If 
    Else 
     If Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), pattern) Then 
      newURL = HttpContext.Current.Request.Url.ToString().ToLower() 
     End If 
    End If 

    If Not newURL Is Nothing Then 
     HttpContext.Current.Response.RedirectPermanent(newURL, True) 
    End If 

End Sub 

Protected Overridable Function GetPageHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler 

    Return TryCast(BuildManager.CreateInstanceFromVirtualPath("/" & _rtLookup.RequestHandler, GetType(Page)), Page) 

End Function 

End Class 

回答

0

好吧,想出發生了什麼事在這裏。 RedirectToRoutePermanent不像RedirectPermanent(url,true)那樣終止請求。我重寫了PageRouter.RedirectToRoutePermanent,因此解決了問題:

Public Shared Sub RedirectToRoutePermanent(rtData As RouteData) 

    Dim route As BaseRoute = DirectCast(rtData.Route, BaseRoute) 
    Dim rtLookup As RouteLookup = route.RouteLookup 
    Dim newRtLookupID As Integer = rtLookup.RedirectedToRoute 
    Dim newRtLookup As RouteLookup = (From rt In db.RouteLookups Where rt.RouteLookupID = newRtLookupID).SingleOrDefault 

    Dim hostAndPort As String = HttpContext.Current.Request.Url.GetComponents(UriComponents.HostAndPort, UriFormat.UriEscaped) 
    Dim newURL As String = Nothing 

    Dim scheme As String = If(rtLookup.IsSecure, "https", "http") 
    newURL = scheme & "://" & hostAndPort 
    newURL &= "/" & newRtLookup.RelativePath 

    If rtData.Values.Count > 1 Then 
     For i As Integer = 1 To rtData.Values.Count - 1 
      newURL &= "/" & rtData.Values(i) 
     Next 
    End If 

    HttpContext.Current.Response.RedirectPermanent(newURL, True) 

End Sub 
相關問題