Threading in ASP.NET MVC 3 - c#

I am currently converting a Windows Phone 7 application to its web counterpart. The application uses a big main thread from which the data is gathered, and for the moment I have just copied and pasted it as is (just a standard thread operation), in my ASP.NET MVC controller.
Sync _Sync = new Sync();
_Sync.StartSync();
The tasks work OK, but because the thread makes use of global data set from the cookies, issues arise when accessing the page with 2 different usernames. For example, if I login with "user1" in Firefox and then try to login in Chrome with another user (say "user2"), then it will automatically change the async data gathered for the first user; meaning that I will always see data pulled out from the last user logged in (regardless of the fact that I was just logged in in Firefox with another user, initially), and not each others' separate data.
In other words, the thread doesn't start separately for each individual user. How could I fix this behavior?

Static fields and properties are shared across threads and should generally not be used to store data that pertains to a specific user or web request.
One of the following suggestions should fix your threading issues and keep your user data separate.
Create an instance of the Sync class for each request and remove any static fields / properties from the class.
Add a method to the Sync class that returns an instance of the data for a specific user instead of storing the data in static fields / properties.

Related

C# Global mutex for MVC?

In MVC if I want to lock a method so that it will never run more than once at a time (despite multiple users using the application), I can just use a static object:
private static Object lock= new Object();
But in my case I want to create a lock with a name, so the application will only lock for those users trying to use the same name.
Normally in C# I would use a Mutex(name) for this, but is there an appropriate equivalent in server world? (it needs to be global for all users)
Edit:
This is a client application, rather than a public site - so there would only ever be max say, 20 users accessing the application at a time.
You do not want to block anything on server side, what you want is to not execute anything on server side once condition is met. It can be handled in number of ways: Error page redirection, Notification to the client about critical condition met...etc
In other words, for selected users, handle that special condition, but
do not block anything.

Do I need a ConcurrentDictionary? Will regular Dictionary do?

I currently am using a ConcurrentDictionary to hold a collection of login names that have authenticated with my API. I do this to prevent duplicate logins from other web clients (a requirement of the system architecture). If a user authenticates with a login that is already "logged in" they are given a choice ...
Continue and the previous login will be expired
Cancel and the current session will be logged out
I am using a ConcurrentDictionary because it is supposed to be thread safe which is important in an environment where multiple clients are accessing the API.
What I am asking is if the ConcurrentDictionary is needed because I am running into trouble deleting all items in the collection that match a given key. Is a ConcurrentDictionary called for in this case? If not, would a plain Dictionary suffice? If not, and a ConcurrentDictionary is needed is there a method that will remove all entries matching a given key? All I can see is TryRemove() which only seems to remove a single entry.
The direct answer to your question:
Yes, you need a ConcurrentDictionary. You are sharing state across several threads.
Remember, a dictionary has one entry per key. That's the definition of what a Dictionary is, and a ConcurrentDictionary doesn't change that.
A fuller and more complete answer to your requirement is below.
The whole solution is short sighted as you have no connection with the session infrastructure to know when a user's session has timed out and effectively caused them to be logged out. Additionally there is no coordination with other instances of your app if you ever think about deploying to a cloud platform that spins up new instances.
In other words, you are putting yourself in a situation that makes it very difficult to scale your app without breaking this feature.
Probably one of the most robust ways of handling the single session requirement is to use your database:
Have a field that keeps track of the last session ID your user had when logging in.
Add a session listener to clear the field when the session times out
If the session ID is not the same as what's in the field, you know you have a new login attempt.
If you need complete control over the session ID, then supply your own session id manager (may be necessary to include an encoded server ID in it).
You'll find that the requirement is much more involved than it sounds on the surface. You can't think like a desktop application in the web space--which is precisely where this requirement even comes from.

Periodically insertion into Azure database with ASP.NET MVC application

I am wondering how to implement a solution that will retrieve data that I have scraped, and use it to display in an ASP.NET MVC web application.
The current implementation scrapes the data and displays it from the controller to the view, however by doing so, the request to view the web page will take very long due to the scraper running when a request to view the page with scraped data is processed.
Is there any implementation I can do to separate the data retrieval and the website?
Currently I have a console application scraper class that scrapes data, and a ASP.NET MVC web application that will display the data. How can I couple them together easily?
Based on system size I think you can do 2 things:
Periodically scrape data and save it in the memory
Periodically scrape data and save it in the database
It is oblivious that if scrapped data is big you need to store it in database, otherwise you can keep it memory and highly boost performance.
Running tasks in asp.net periodically is covered by background workers. Some easy way to periodically run tasks is to initiate thread in Application_Start. I don't go more deeply in implementation, because it is already answered. You can reed it here: Best way to run scheduled tasks
For saving data in memory you can use something like this:
public static class Global
{
public static ConcurrentBag<ScrapedItem> ScrapedItems;
}
*Note, it is necessary to use thread-safe collection, because of getting and adding to this collection will be done from different threads: one from background worker, one from request. Or you can use lock object when getting/setting to not thread safe collection.

.NET Session Alternative in Global Scope

Quick question: Is there a "per-user" data storage object (similar to Session) that I can store data in the global scope (similar to HttpRuntime.Cache)? Almost as if Session and HttpRuntime.Cache had a baby.
Full Background: I have a ASP.NET website that was originally written for a single thread. Now I changed it so that certain actions will spawn a background thread and the browser polls a service to get status updates.
The problem I am having with this is that certain pieces of data are stored into the HttpContext.Session[] object (membership authentication token, for example). These pieces of data need to be unique to each user and accessible to the background thread. Session is not available to the background thread.
I am aware of HttpRuntime.Cache but that would require micromanagement to segment out the users and to expire it at the same time the session is expired. Session, on the other hand, automatically expires this things at the right times that I want it too and is already used by things like the SqlMembershipProvider.
My question is, is there something that behaves similar to the Session but exists in the global scope?
I don't think there is anything like you need out of the box. I would do the following though:
User the application cache
Make the key the user ID or unique identifier
Store a Dictionary or some object list in the value for the user. Use this to store all the data you require.
Consider all prepending something on the user ID if you think there could be a conflict with the user unique identifier (eg domain etc)
Make sure to set an expiry on the cached data similar to the session (eg sliding)
Try passing the HttpContext.Current object to the method on your background thread. You should be able to access the session from the background thread through currentContext.Session assuming currentContext is the HttpContext parameter that was passed in.
See this blog post on how to safely access the HttpContext object from multiple threads.
No.
Since when application pool restarts all backgound activity die I suggest to think about moving user's state to your own database or external storage. Unfortunately you'll lose automatic session management benifits (sliding expiration), but if you need backgound activity it will work better - i.e. you'll be able to move your activity out of IIS process to separate process/machine if needed later.

Uniquely identify two instances of one browser that share Session state?

I want to ensure a user isn't editing the same form data in two different browser tabs or windows (of the same web browser instance). The intention is to stop the user from accidentally overwriting their own data as they continue through a very long form process. On the server, ongoing data input through the screens is collected into the Session.
Assume for any browser, all tabs and windows run in the same instance of it (i.e. not each in a separate process). Obviously the browser tabs and windows share the same cookies in this scenario so cookie modification seems out of the question for viable solutions. This is also the reason they are sharing the same session state.
Considering that the form is already created and this is one of the final touches, how can I use ASP.NET, hopefully easily, to oversee this
"feature"?
You could try something like this:
Store an integer as Session["LastRequest"]. Put this into a hidden field on the page. For every request, you add one to the integer.
On postback, make sure that no other request has been made by checking that Request.Form["LastRequest"] is equal to Session["LastRequest"].
If you need to check for multiple instances before the postback happens you should be able to do so using AJAX calls.
Every time you render a form, set the value of some hidden field to random string. Store the same string in Session state. When the user posts back, check if the two values are equal. If not, this must be a re-post.
You cannot distinguish two http POSTs for the same page even if they are from different tabs.
It's like the famous back-button problem - they can post, press back, and repost.
The usual solution is hidden tracking fields, but it's very hard to make them reliable.
If it's a wizard-type process, it should be simple to detect if they are overwriting fields that have already been entered, and show a warning.
During the rendering of your specified page, generate a GUID and save in session. Write a generic handler, that keep track that for a specified page, no two GUID exists.
Following data structure will help.
class MultipleOpenedPage{
string guid;
string pageURL;
DateTime timeStamp;
bool IsMultiplePageOpened(List<MultipleOpenedPage> list)
{
///logic
}
}
Because of the stateless nature of the web, I don't believe there is a reliable way to differentiate between two browser windows. However, you can store a flag in Session that a given long running process is in progress. In this way, you don't care if they try to rerun the process from the same browser window or multiple browser windows. The trick is going to be handling situations where the process fails and doesn't get a chance to reset the flag so that the process can be run again.
I got round this by creating a base class inheriting from System.Web.UI.Page and in the page_load/init event, creating an object containing information specific to the user instance.
This was, each new page that's created get's it own instance of the object and can therefore maintain different states/properties which can be used to make distinct edits to data on the same page.
Just a thought as it's a bit of a different way around things.

Categories