ASP.NET MVC中多个浏览器标签页的唯一会话

10

我希望在ASP.NET MVC应用程序中,每当用户打开新的浏览器选项卡或窗口时,都能创建唯一的会话。在ASP.NET/MVC中是否可能实现?

我尝试了以下解决方案:

asp.net - session - multiple browser tabs - different sessions?

但是它在ASP.NET MVC中无效。上面的解决方案使用ViewState,在MVC中我尝试使用TempData,但它不起作用。


你尝试过使用Session吗? - meda
您的服务器无法知道用户何时在新标签页中打开页面。(某些浏览器可能具有此类扩展程序,但您的99.999%用户不会使用)。 - Andrew Barber
它与Session不兼容,因为会话值被覆盖而无法正常工作。 - Pinal Dave
3个回答

7

多年过去了,我终于找到了解决这个问题的方法:

1.) 浏览器必须自行提供ID,因为HTTP是无状态的,cookie不会单独存储浏览器标签页,ASP.NET会话也不能区分单个标签页。

2.) 在打开新标签页时,JS窗口名称为''。将窗口名称更改为某个值后,只要标签页仍然存在且没有被某些代码更改,它就不会再更改。

因此,解决方案是:在 *.master 或每个 *.aspx 文件中实现一些简短的JS代码:

 if (typeof window.name != undefined) {
             if (window.name == '') {
                 var d = new Date();
                 window.name = '_myWnd_' + d.getUTCHours() + d.getUTCMinutes() + d.getUTCSeconds() + d.getUTCMilliseconds();
             }
             var eDiv = document.getElementById('div_BrowserWindowName');
             var e = eDiv.getElementsByTagName('input')[0];
             e.value = window.name;
         }

在*.master或每个*.aspx文件的表单部分中添加以下内容:
 <div id="div_BrowserWindowName" style="visibility:hidden;">
                <asp:HiddenField ID="hf_BrowserWindowName" runat="server" />
            </div>

现在,您可以在每次回传后通过读取隐藏字段来检索窗口名称 == 唯一标识符,即使用户在跳转到其他网站并在几小时后返回表单。


1
我正在尝试想象这种方法中的所有陷阱。您能否分享一下您是否仍然推荐使用这种技术? - Kristopher
1
那么MVC呢? - usefulBee

2
正如你所知,HTTP是无状态的,而在请求之间保持状态的一种非常常见的机制是使用会话变量。问题发生在你打开新的浏览器选项卡时,因为会话是相同的,所以你在新选项卡中所做的任何更改都会影响到其他选项卡。如果您有一个产品列表页面,用户可以输入搜索过滤器,并希望将它们保存在会话中,但用户在选项卡1中设置了搜索过滤器值,则选项卡2将具有相同的值(它们共享会话变量)。那么你该怎么办呢?
1)使用此方法在URL中添加guid:http://www.codeproject.com/Articles/331609/Get-an-unique-session-in-each-browser-tab 2)类似于上一个点中描述的方式,但不完全相同,这就是我解决同样问题所采用的方法。
a)我的链接到搜索页面是/Product/List?guid=xxx而不仅仅是/Product/List。如果用户手动键入/Product/List,我将重定向他到一个新的URL,其中GUID已设置。
public ActionResult List(string guid)
        {
            if (guid == null)
            {
                return RedirectToAction("List", new { guid = Guid.NewGuid().ToString() });
            }
...

每当您点击“列表”链接并定位到新标签时,都会生成一个新的GUID。

b) 我有一个带有GUID的会话密钥,因此每个页面都有自己的值。您可以同时打开2个标签,并且它们将使用不同的会话值,因为GUID将是不同的。

这种解决方案并不完美,但至少它能够正常运作。

希望这些能够有所帮助。


0
第一个答案的变体,使用HTML 5,是使用window.sessionStorage而不是设置window.name。因此,您可以在应用程序的入口页面上执行以下操作:
var uniqueId = "<%= Guid.NewGuid().ToString() %>";
window.sessionStorage.setItem("tabId", uniqueId);

然后在每个需要会话的控制器操作中,您都要传递该参数:

window.sessionStorage.getItem("tabId");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接