为什么重定向到路由永久将"count=0"添加到查询字符串?



我正在使用 ASP.NET 4.0路由,正在从数据库中读取路由信息并添加路由,如下所示。简而言之,我的自定义对象"RouteLookup"包含路由信息,包括另一个RouteLookup的ID,它可能被重定向到,也可能不会被重定向到。下面是数据库中两个 RouteLookup 条目的示例:

    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 结果时,它实际上重定向了两次并添加"count=0"作为查询字符串参数!我不知道这个参数来自哪里,因为我没有明确添加的进程、httphandler 等。

这到底是怎么回事?非常感谢任何想法,其余相关代码如下。

我有一个类,BaseRoute,它继承自Route,所以我可以传递我的自定义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

自定义路由处理程序:

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

好吧,弄清楚这里发生了什么。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

最新更新