0

我在网上看到几篇帖子抱怨 Firefox 在重定向后维护历史 url 哈希。这是我希望的行为 - 它发生在 Firefox (11.0)、Chrome (18.0) 和 Opera (11.61) 中,但不是 IE (9) 或 Safari (5.1.2)。

在我的页面上,我设置并运行了 ASP.NET 4.0 历史记录点(已经工作了几年)。我还将一些查询字符串参数传递给页面。我现在要做的是检查新查询字符串参数的值,如果它与我的期望不匹配,则使用更新的值重定向到同一页面。我正在使用这种机制来跟踪浏览器的各个选项卡的会话,以便当它们在多个选项卡中打开相同的页面时,会话值不会从一个选项卡到另一个选项卡。

无论如何,我的一切工作正常,包括使用 ASP.NET 历史记录点的后退/前进 - 当我访问书签并且查询字符串参数不匹配时,我重定向并更改查询字符串参数以跟踪会话,以及历史状态是在书签的 url 然后用于将页面重新加载到我想要的状态。但这仅适用于 Firefox、Chrome 和 Opera。不是 IE,它对我来说很重要(仅基于我们的用户群),而不是 Safari。

我已经确定除了(或者可能是因为)不存在 url 历史状态这一事实之外,在 IE 或 Safari 中重定向后不会调用 ScriptManager.Navigate。

是否有我可以在 ScriptManager 上或在重定向期间设置的设置/选项以维护 url 中的历史状态? 如果历史状态在 url 中,如果需要,我可以直接调用 ScriptManager.Navigate,但值不存在于 url 中。

如果它有帮助,这里列出了我在哪里进行检查和重定向。然后将 ReportRunID 附加到每个选项卡需要唯一的会话变量键。我保留了以前 ReportRunID 的列表以跟踪并清除它们(在某个时间段之后,或者遇到超过 [MAX] 个 id 时),这样我就不会因为这些会话条目而使服务器内存过载。

Private Sub Page_PreInit(sender As Object, e As System.EventArgs) Handles Me.PreInit

    If IsPostBack = False Then
        Dim rrid As String = Request.QueryString("RRID")
        If ReportRunIDExists(rrid) = False Then
            ReportRunID = Now.ToString("_HHmmssfff")
            Dim url As String = Request.Url.PathAndQuery

            If String.IsNullOrEmpty(rrid) Then
                Response.Redirect(String.Format("{0}&RRID={1}", url, _reportRunID))
            Else
                Dim idx As Integer = url.IndexOf("&RRID=")
                Response.Redirect(String.Format("{0}&RRID={1}{2}", url.Substring(0, idx), _reportRunID, url.Substring(idx + 6 + rrid.Length)))
            End If
        End If
    End If

End Sub

Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
    'save current RRID/Page/Time to session
    UpdateSessionReportRunID(_reportRunID)
End Sub

...

如果我的书签网址看起来像:

mysite.com/mypage.aspx?Rpt=123&RRID=_095224678#&&state1=abc&state2=def...

在重定向后的 FF/Chrome/Opera 中,我的网址如下所示:

mysite.com/mypage.aspx?Rpt=123&RRID=_102176253#&&state1=abc&state2=def...

但是在重定向后的 IE/Safari 中,我的 url 看起来像:

mysite.com/mypage.aspx?Rpt=123&RRID=_102176253

有任何想法吗?

4

1 回答 1

1

经过更多的搜索,我意识到历史状态哈希没有发送到服务器。它存储在查询字符串中,因此它包含在书签中,但它由客户端脚本管理器访问,这会导致回发加载状态值。由于服务器从未在查询字符串中看到哈希值,因此当用户关注该页面的书签时,我无法找到这些值。

当我试图开始单独跟踪不同浏览器选项卡的会话状态时,引入了这个问题。在上面的代码中,如果参数为空或无效,我必须使用新值RRID重定向到 self 。RRID当我这样做重定向时,IE 和 Safari 的历史状态哈希丢失了(但其他浏览器没有)。

我的解决方法:

问题是我需要在我的重定向中包含哈希值,但这在服务器上不可用,所以我决定向页面注入一些 javascript 以从哈希可用的客户端执行重定向。

我已经有一个在不同场景中使用过的客户端重定向扩展助手方法,我对其进行了修改以包含当前的哈希值:

<System.Runtime.CompilerServices.Extension()>
Public Sub ClientRedirect(ByVal Response As HttpResponse, ByVal url As String, Optional ByVal target As Target = Nothing, Optional ByVal windowFeatures As String = Nothing, Optional includeCurrentHash As Boolean = False)

    If IsNothing(target) Then
        If windowFeatures = String.Empty Then
            target = ResponseHelper.Target._self
        Else
            target = ResponseHelper.Target._blank
        End If
    End If

    Dim page As Page = CType(HttpContext.Current.Handler, Page)
    url = page.ResolveClientUrl(url)

    Dim script As String
    script = "window.open(""{0}"", ""{1}"", ""{2}"");"

    script = String.Format(script, url & If(includeCurrentHash, "#"" + window.location.hash + """, String.Empty), target.ToString, windowFeatures)
    If target = ResponseHelper.Target._self Then
        'execute after page has loaded
        page.ClientScript.RegisterStartupScript(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
    Else
        'execute as page is loading
        page.ClientScript.RegisterClientScriptBlock(GetType(Page), "Redirect_" & Now.ToString("HHmmssfff"), script, True)
    End If

End Sub

然后在我进行重定向的 Page_PreInit 中,我将其更改为包含当前哈希的 ClientRedirect,并且得到了预期的结果:
重定向浏览器,同时在所有浏览器上保持历史状态哈希。

    'redirect from the client so that we keep the History State URL hash 
    Response.ClientRedirect(String.Format("{0}&RRID={1}", Request.Url.PathAndQuery, _reportRunID), , , True)
于 2012-04-13T20:28:49.123 回答