How to eliminate if end user open the same ASP.NET page in another tab

Gani_tpt 2,092 Reputation points
2024-06-18T14:39:10.5133333+00:00

This is simple question.

I am developing ASP.NET application and sharing the hosted URL to end user.

some times end user opens the same page in multiple tab.

i want to control, either should not allow the same page in another tab or redirect some unauthorized page.

Give me some suggestion pls.

ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,394 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,562 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Michael Taylor 50,506 Reputation points
    2024-06-18T15:15:53.2466667+00:00

    You really cannot stop that and I'm curious why you would. If your system cannot handle having the user in the same tab multiple times then you have a concurrency issue and should resolve it.

    Nevertheless let's talk about what you would need to do to implement this kind of functionality. Whether that is doable for you is a different discussion.

    1. You need to be able to uniquely identify the user across browsers (this covers tabs, windows and browsers). If you require the user to log into your system (or you're using Windows auth) then you can use the user's account.
    2. You need to detect multiple sessions. A session could be another tab, another window or a different browser altogether. This would also include if the user used a different device altogether. For another tab there are 2 cases: they duplicated the existing tab or they opened in a new tab. In cases where a new tab/window/device was used you can have the client auto-generate some unique identifier. Note that this might not work correctly if the tab is duplicated. Also note that ASP.NET session isn't sufficient here as it is just a value that is passed from client to server and duplicating a tab doesn't change the session.
    3. Given the user ID and their "session ID" then you'd need to pass that data back to the server and the server would have to respond to whether the "session" should be allowed by determining if the user already has a different session open. Because the user may be interacting with your site and may at any time create a new tab then this would need to be a polling call such that you check periodically. The more frequently you check the more resources you use.
    4. At some point you need to clean up the session information. The user closing a tab, window, device would need to disconnect the session but since none of that is reliable you'll be in a situation where a user may "close" a session but another session may still be active. This is going to cause false positives.

    Honestly this is going to be ugly to solve. An alternative approach is to handle it all on the client side. You could create a local storage object on the client that marks the session in use. Whenever a new tab, window, device is opened then you check for the existence of the local storage object and fail the call if it exists. It has some similar problems though including the fact that it might not get cleaned up properly in all cases. You would have to guarantee that it is removed when the tab closes so maybe session storage on the client would be a good choice. But I don't know how session storage works across windows.

    The problem with doing things on the client is it only works for a single browser and device. If you created client storage for Edge and then switched to Chrome it wouldn't have access to the storage as that is browser specific. Even if the browsers share the same storage on a device it is still possible to work around by using multiple devices.

    Overall this seems like a problem that shouldn't be solved as it doesn't really accomplish anything. If you really need the feature then you're looking at something server side but that is hard to implement properly. Client side is probably easier but it is limited.

    0 comments No comments

  2. Bruce (SqlWork.com) 60,201 Reputation points
    2024-06-18T15:49:27.65+00:00

    the tabs hosting the same site share the same cookies and local storage. this can cause issues if the code does not expect this (temp storage, server state, etc). you should update the site to support concurrent sessions.

    in modern browsers you can use broadcast api:

    https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API

    also you can use local storage events. use a common property as a flag (say set a "login" flag):

    https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event

    0 comments No comments

  3. Albert Kallal 5,226 Reputation points
    2024-06-18T21:50:19.58+00:00

    As pointed out, due to the so called state-less nature of web pages?

    Then often the better solution is to write the code behind in such a way that it does not matter if they have one, or many tabs open.

    So we have:

    ViewState = per page, client side storage - allows multiple pages open to same URL, each page will have its OWN ViewState, which is great.

    Session() = global to the one user, and hence for a given open page, then values are shared between all pages open, including multiple pages on the same URL.

    So, if the session() values are not large?

    Then a great approach is this:

    Use session to pass values to the next page in question.

    On first page page load transfer session() values to ViewState.

    So, say on previous page was some GridView, or search for a project page.

    When the user clicks on that given row, then I create a instance of my ProjectInfo class.

    I used a simple class, since I had/have about 8 values I need to pass to the next page (and then code behind also needs to work with those variables.

    So, I setup the object, navigate to that next page, but FIRST thing I do is transfer the object from session to ViewState. This allows then multiple instances of the same page to be used, but the two pages have their own values, since we used Viewstate -- which is per page, not per user.

    Hence, lots of code looks like this:

    Previous page - user selected some project or whatever, and then we navigate to the page to work on this one project.

    Then, on page load, we do this:

            public clsTax cTax = new clsTax();
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    cTax = (clsTax)Session["TaxRate"];
                    ViewState["TaxRate"] = cTax;  // transfer to this page only
                }
                else
                {
                    cTax = (clsTax)ViewState["TaxRate"];
                }
            }
    
    

    So, note how we scoped the class to the current page, and thus any button click and any and all code behind can freely use that persisted class object.

    So, in effect, in place of trying to build some code (which is difficult) to prevent multiple instnaces of the same tab opened, then you are far better off to simply write code that allows multiple instances of the browser to be open and not worry or care.

    The second approach I often use for larger sets of data that I have in Session[]?

    Well, the issue is that ViewState is client side, and it will make the round trip on each and every post-back. This thus can be a performance issue, since ViewState becomes part of the browser post-back payload each and every time. So, while both Session[] and ViewState are to be treated like gold, used with great caution, and kept to the smallest size possible?

    Well, for browser performance, then of course session[] is often the better choice.

    So, in such cases, then what you do is generate a incrementing number, or even use a GUID. You save that value into a hidden field, and then use that as the key value to pull the object from session.

    So, on page load, we again transfer the class from session[] into a key value session[] for that ONE given page. Once again, the result is not you preventing multiple tabs to the same page being opened, but that of allowing the code to correctly operate and freely operate even when multiple instances of the page are open.

    Of course, this suggests far more care be taken, and not having a whole bunch of variables persisted into Session[], but suggests that some class with all the values + variables be created, and hence you not cluttering up session[] with a boatload of separate variables.

    Since session[] is global to all pages for the user, then that in effect means your using global variables, and if you have lots of them, then your code becomes progressively harder to write and manage, since you be asking is some other page, using that session variable??

    So, try to adopt the design pattern that session[] is used to pass/transfer values to the target page, but once on that target page, you transfer over to ViewState, or you transfer over to a key value session that is unique to that one given page.

    Having stated all the above?

    You can try to adopt code to prevent multiple pages being opened to the same page by the one user. Note how I used the term "multiple pages", since "tabs" don't matter - they are considered separate pages. In fact, the user might have multiple instances of the browser launched, or maybe even different browsers running - say Firefox and Edge. So, once again, it can be a real challenge to prevent multiple pages being opened to the same URL. While on that tab, the user now might have decided to jump to some shopping site, and once again, you see how difficult it can be determine if other pages are open by one user to the same URL. So, in most cases, you find it far less work to adopt the above ViewState design pattern, and as a result, it should not matter if the user has 1 or 5 tabs open to that one URL.

    If you absolute need to only allow one URL from the user, then I suggest adopting web Sockets to achieve this goal. Since it can be quite a bit of work to setup your own custom web socket, then most will adopt a pre-built one for such goals.

    A popular .net web socket library is thus SignalR, and it does allow real time updates of a web page (this is how say a chat page can work, and also how push notifications from the server to the client side browser is done).

    You can start reading here:

    https://dotnet.microsoft.com/en-us/apps/aspnet/signalr

    0 comments No comments