Davide De Santis
Davide De Santis

Reputation: 1035

Static class with non-static members shared across instances of ASP.NET MVC app?

I have a solution with several projects, including an ASP.NET MVC project and a WPF application. In the DB, I have some general settings which I want to use in both applications. To do that, I've created a class library Foo which loads the settings into a dictionary and provides a Get(string key) method for accessing specific settings out of the dictionary. Since the settings can be overridden by user, I've added a property containing the UserId. The Get() method automatically takes care of checking and using the UserId property. This way, I don't need to pass the UserId as a param each time I call the Get() method.

For the WPF application, this works just fine, since there is just one instance running. However for the web project, I'd like to have the dictionary filled only once (in Application_Start()) and be accessible to all users visiting the site. This works fine if I make the class instance static. However, that does not allow me to have different UserIds, as this would be overridden for everyone with every user that accesses the site. What's the best way to solve this?

Here's what I tried so far (very simplified):

Class Library:

public class Foo ()
{
    private Dictionary<string, string> Res;
    private int UserId;

    public Foo ()
    {
        Res = DoSomeMagicAndGetMyDbValues();
    }

    public void SetUser (int userId)
    {
        UserId = userId;
    }

    public string Get(string key)
    {
        var res = Res[key];

        // do some magic stuff with the UserId

        return res;
    }
}

Global.asax:

public static Foo MyFoo;

protected void Application_Start()
{
    MyFoo = new Foo();
}

UserController.cs:

public ActionResult Login(int userId)
{
    MvcApplication.MyFoo.SetUser(userId); // <-- this sets the same UserId for all instances
}

Upvotes: 0

Views: 281

Answers (1)

Rufus L
Rufus L

Reputation: 37030

What about storing the settings in a Dictionary<int<Dictionary<string, string>>, where the Key of the outer dictionary is the UserId, with key 0 saved for the default settings? Of course this means you'd have to pass the user id to the Get and Set methods...

Then, you could possibly do something like this:

public static class Foo
{
    private static Dictionary<int, Dictionary<string, string>> settings;

    /// <summary>
    /// Populates settings[0] with the default settings for the application
    /// </summary>
    public static void LoadDefaultSettings()
    {
        if (!settings.ContainsKey(0))
        {
            settings.Add(0, new Dictionary<string, string>());
        }

        // Some magic that loads the default settings into settings[0]
        settings[0] = GetDefaultSettings();
    }

    /// <summary>
    /// Adds a user-defined key or overrides a default key value with a User-specified value
    /// </summary>
    /// <param name="key">The key to add or override</param>
    /// <param name="value">The key's value</param>
    public static void Set(string key, string value, int userId)
    {
        if (!settings.ContainsKey(userId))
        {
            settings.Add(userId, new Dictionary<string, string>());
        }

        settings[userId][key] = value;
    }

    /// <summary>
    /// Gets the User-defined value for the specified key if it exists, 
    /// otherwise the default value is returned.
    /// </summary>
    /// <param name="key">The key to search for</param>
    /// <returns>The value of specified key, or empty string if it doens't exist</returns>
    public static string Get(string key, int userId)
    {
        if (settings.ContainsKey(userId) && settings[userId].ContainsKey(key))
        {
            return settings[userId][key];
        }

        return settings[0].ContainsKey(key) ? settings[0][key] : string.Empty;
    }        
}

Upvotes: 1

Related Questions