I created a static class to hold user messages such as “Item successfully added” or “Password successfully changed”, etc. Inside the class is a static dictionary which holds all the messages. The key of the dictionary is the UserId. I then have an Action which renders in _Layout.cshtml so that the messages will follow the user even if they are redirected off the page.
For example, I might allow a user to “Add” an item, and then once the item is added successfully, it will redirect to the List page for that item and then display the message “Item successfully added.”
This worked great until I deployed to my production site and I noticed that the messages were “lagging”. I would add an item and then it would redirect to the list page, but the message would not display. I would then navigate to somewhere else in the application and then the message would display on that page.
Any ideas why this would be happening?
Here’s the code for my UserMessageManager
public static class UserMessageManager
{
private static readonly Dictionary<int, Queue<UserMessage>> UserMessages = new Dictionary<int, Queue<UserMessage>>();
public static void Add(int userId, string message)
{
if (string.IsNullOrWhiteSpace(message))
return;
if (!UserMessages.Keys.Contains(userId))
{
UserMessages.Add(userId, new Queue<UserMessage>());
}
UserMessages[userId].Enqueue(new UserMessage { Message = message});
}
public static List<UserMessage> Get(int userId)
{
if (!UserMessages.Keys.Contains(userId))
{
UserMessages.Add(userId, new Queue<UserMessage>());
}
var messages = new List<UserMessage>();
while (UserMessages[userId].Any())
{
messages.Add(UserMessages[userId].Dequeue());
}
return messages;
}
}
public class UserMessage
{
public string Message { get; set; }
}
EDIT: After some playing around, the messages will sometimes even “bunch up”. I will add a messages to the dictionary after creating a few “items” and the messages will suddenly all display at once at a seemingly random time.
Firstly, if this is for a real site, I wouldn’t take this approach anyway. If you want information persisted, use something persistent (e.g. a database). Otherwise when the AppDomain is recycled or the whole server goes down (you do have redundancy, right?) you’ll lose all the messages. This approach also doesn’t load balance nicely.
Secondly, it’s just possible that you’re seeing the results of the standard collection classes not being thread-safe. Without any synchronization or other memory barriers, it’s possible that one thread isn’t seeing the data written by another. It would also be entirely possible for two threads to write to the dictionary (or write to the same list) at the same time. You could just add some synchronization, e.g. have a lock object and lock on it for the entirety of each method. I’d start using a database instead though…