0

I'm trying to implement web application and using a singleton object so I would be able to inject it to use it in other classes. I want to open a new object every time the user opens a tab or similar in the browser. For example:

public class Singleton
{
    public string Id{get;set;}
    public Singleton(){Id=Guid.NewGuid().ToString();)
}

in startup:
services.AddSingleton<Singleton>(s=>new Singleton());

In some other class:

public class OtherClass{
    private readonly Singleton singleton;
    public OtherClass(Singleton singleton)
    {
        this.singleton = singleton;
    }
}

The problem is that every tab has the same Id... I need a different id for every tab in the browser...

Thanks!

Nadav
  • 49
  • 7
  • 6
    The whole point of a singleton is to be only one instance. Use `AddTransient()` instead. – Tobias Tengler May 07 '19 at 08:14
  • but in this case I'll have different id for every class – Nadav May 07 '19 at 08:16
  • ASP has no way to determine the browser tab a request is coming from (without additional work), it works on a per request basis. – Tobias Tengler May 07 '19 at 08:17
  • So what can i do...? If I want to have an object in the whole application, for each instance? – Nadav May 07 '19 at 08:22
  • 2
    @Nadav Tobias already explained that *singleton* means *single* instance. You ask for the *opposite*, a *different* instance for each ... what? A web server, **any** web server, knows nothing about browser tabs. Tabs are no different than separate browsers or even machines as far as the server is concerned. Web servers know only about requests and responses. Application servers like ASP.NET and later also know about user sessions. – Panagiotis Kanavos May 07 '19 at 08:26
  • 1
    There is no good way to do this, since it's not something ASP nor .NET Core's Dependency Injection is designed for. Maybe explain what exactly you're trying to do, maybe there's an overall better approach to the main problem your trying to solve. – Tobias Tengler May 07 '19 at 08:27
  • 2
    @Nadav looks like this is an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You have a problem X and think that Y is the solution, so when that doesn't work you ask about Y, not X. What is the *actual* problem? It sounds like you want to keep state, which is typically done using user sessions, but you want to keep that state per *tab*? Why? Does the *same* user need to have multiple sessions perhaps? Or display different "views" in the same session? Why not use different URLs then? – Panagiotis Kanavos May 07 '19 at 08:29
  • I'm trying to create a "session" for each application that the user opens. The user can open multiple applications (for example by tabs in the browser). Each session will contain some details about this current tab(or application or instance or whatever you want to call it) – Nadav May 07 '19 at 08:36
  • Why does the session need to be different in each tab? What does that achieve in terms of usage of your application? It's a very unusual way to do it...also very difficult because the browser sees all tabs as part of the same session, so if you access the same server in different tabs the browser will send the same session cookie in all those tabs. The server will not be able to tell the difference between each tab. Normally it the user wants to initiate a separate session for any reason they must open incognito mode or use another browser entirely. – ADyson May 07 '19 at 09:29

2 Answers2

0

You have to make an Interface for the class you want to be a singleton. You register it in your Startup.cs as a Singleton

public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<ISingleton, Singleton>();
}

You then proceed to inject the singleton interface into OtherClass

public class OtherClass{
private readonly Singleton singleton;
public OtherClass(ISingleton singleton)
{
    this.singleton = singleton;
}

Hope this helps

axelrotter
  • 694
  • 4
  • 22
0

Ok I've found some solution.... I'm creating a singleton class that has an object that will change ... When I want to change the object details, I do this in a method... Then I have the updated information for all the WebApp. The change will be made in every method that I need to specify the object details... For example:

public class InjectedSingleton
{
    public MySession CurrentSession{get;set;}

    public void SetSession(string sessionId)
    {
        CurrentSession = GetSessionById(sessionId);
    }
    public void NewSession()
    {
        CurrentSession = new MySession();
    }
}

public class DoClass
{
    private InjectedSingleton inj;
    public DoClass(InjectedSingleton inj)
    {
        this.inj = inj;
    }
    public void OpenNewTab(string sessionId)
    {
        inj.SetSession(sessionId);
    }
    public void JustShowSomething()
    {
        Show(inj.CurrentSession.Id);

    }      
}

Now, the updated session is the required one, for everywhere in the app for the current user

Nadav
  • 49
  • 7