I'm so confused here. Ok, so I'm trying to create a session object that we can use to store some info.
My plan is to create a new FacebookSession object whenever a user logs into Facebook (after they are redirect back to our site). I can set state for this by using the auto generated cookie that the facebook SDK creates after they've logged into facebook. So I can hopefully grab that cookie when they get back server-side and create my FacebookSession object and set state off the cookie info (userID, token, etc.) that contains info I need for that user's facebook account.
I don't understand session state very well and also threads as it relates to a page. So, can't I check for the existing session object on every page or is it lost when you go from page to page? Lets say I create this initial FacebookSession object when the user gets back and then redirect them immediately thereafter to another page Response.Redirect. Do I lose that object? I think so right? because a new page request spawns a new thread in IIS for that user right? And then you start off with a clean slate in terms of any objects you created in memory have been wiped.
So then I need to persist it in the DB and then with a method such as GetCurrentSession, somehow look up that current user and try to grab current session information in a table lets say called FacebookSession where I could store their facebookUserID, token, etc.
right?
Finally, at any time, how would I know how to check for that user in the DB? I need some sort of unique ID? So what I did was to add a Pk column that actually will utilize an existing sessionID every user on our site has..which is the overall global vistiting session that they get when they visit our site.
So using that I can uniquely identify their facebook Session if it exists by looking it up in my table via their "global session ID". But the problem ultimately that I run into is now in order to call GetCurrentSession() from my FacebookSession.cs object, I need to somehow pass it that global ID. I can do this through the constructor (I'm not making this a singleton). But then now that object and several other objects are dependent on this global ID needed to look up a user's Facebook session. Well what if we want to reuse this library/wrapper I've created in some other project that doesn't want to use the global session as the PK, then I'm kinda screwed.
So this is the headache I have right now. Pretty much I just want some opinions and verification if I'm going down the right path here and if I'm right about memory, IIS, threads, and session state in terms of a way to attack this one.
I guess you should check this description from MSDN.
Related
I have a custom object that is referenced many times throughout a module in my system. Let me refer to it as CustomObj. To minimize the constant loading of this object from the DB I'd like to store it in Session in a collection of those objects. So I'd like to store a Dictionary of CustomObj where the key is the ID of the CustomObj. That way I can just check the Session if they key exists, then just reference that CustomObj over and over again, without the hit on the DB every time.
However, these CustomObjs can be updated by an Admin and their properties change. When that happens I'd like to broadcast down to the users connected to update that object in the dictionary to use the latest properties. Is there a built in process for doing this or would I need to implement some sort of broadcast and force an update via SignalR (I already have a hub setup for Facebook like notifications). Is Session the right place for this ?
The objects won't be updated extremely frequently or by alot of different Admins, but every once in a while the Admin will make a change to 1-5 properties, save, and the object is now different.
It's not an ideal way to store an object in a session that is being modified by different users. In your case, Caching should be the recommended solution.
I am trying to add an item to the users Identity, but I think this could also be done another way.
I have added a few custom fields to the User Identity, but what I am trying to do is once the user has successfully logged in, I check if they are assigned to multiple branches(Store Locations) and then offer a list for the user to select which Branches they want data to be displayed for.
I have done this successfully, but now I want to store each of the branches in the users session/ cookie/ Identity (not sure what terminology to use). The user is displayed a number of checkboxes, and once they click save, I am unsure of what to do.
I need to save it in this function:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SelectBranch(params string[] branchNames)
{
foreach (var branch in branchNames)
{
//add branch to session/cookie/identity
}
return RedirectToAction("Index");
}
What steps do I need to take to be able to do this?
It depends on what you end goals are. Should the choice of branches be persistent or transient? Based on your comment, it sounds like you're wanting to save it for the current session, but then make the user choose again the next time they come back. If that's what you application truly needs, fine, but it seems to me that something like this should either be saved permanently, with the ability for the user to update those choices when they see fit, or completely temporary, i.e. for the current request, such as filtering a set of results by a branch or branches.
Storing for only the current browser session begs the question of whether the user will realize that their choices are being persisted across additional views, and conversely, whether they'll understand why they have to continually set branches each time they come back to the site.
That said, your choices:
Permanent - Store on user entity. Add a M2M between ApplicationUser and StoreBranch (or whatever).
Transient - Set in Session.
Technically, you can use claims, but they aren't really a good fit for this. Claims should be used when either 1) the data being stored is not applicable to every user or 2) the data being stored is transient in nature, but should survive the session. A good example use of a claim would be storing an auth token from something like Facebook. Not every user will necessarily have a Facebook auth token, so it's not something you would want as a database column, and there's generally a lifetime for that auth token, making it temporary but still something you would need to hold on to even if the session was destroyed.
Based on your description of what you want to achieve, Session is your best bet, but I would argue strongly that there's probably value in persisting this choice permanently, as long as the use can alter it later. To save it to the session, I would literally just save your string array directly to the session (no need for the for loop):
Session["BranchNames"] = branchNames;
I would tell you to use Identity claims
What is a Claim?
A Claim is a statement about the user makes about itself, it can be user
name, first name, last name, gender, phone, the roles user assigned
to, etc…
You can know more about them here
I have 3 pages to get details of user and I'm confused what to do with users' temp data
whether
store in database and delete incomplete form data using scheduler
store in session for that user
store in cookies
All of the options you mention are valid in some cases.
I would not go for the cookies option since they are sent along with every request and the data could get too large.
If you want to keep information over sessions the database is your only option. Else wise choose the option you seem best.
It depends upon the requirement. The easiest will be session since clearing the data is not required .net will do it automatically on session-expire.
storing in database and cookie will result in more code. If you want to use the best option go for cookie it will use the least server resources, but the round trip can be costly if there are many cookies. since cookies also get transmitted every time u make a request.
The other options that you can think of is using the view state to persist the data. It will require the most code to accomplish, but will be the best since the data is only be kept till the user is completing the form. you will have to take one page data and pass it to another page in view state and so on.
1.if you use database then this option requires DB trips that is not good and it also effects to your application performance.
2.Session will be the best option to store user Temp data.With sessions you can use datatable object and then this datatable is assigned to session variable.
3.it creates a problem if some user disable browser's cookies.
Happy coding....
I want to store a user setting(language). so i can get the corresponding resources when the page loads. I figured cookies would be the way to go, but it's just not an option, too difficult since i have tried and tried without success.
After 2 days i want to give up on cookies and see if there is another way I can achieve the same goal
i've read this article http://msdn.microsoft.com/en-us/library/ms178581.aspx
but im not sure if I can achieve what I want using that.
What alternatives for cookies could i use in my situation?
Depending on the level of persistence you're looking for, there are a couple of other ways you can do this. The first is to use session to hold these settings. However, if you use session the settings will only live as long as the session does. If your website has some kind of authentication interface, you can store the settings in a database relative to the username used for authentication. If you don't have authentication involved and simply want to remember that the user came with a particular computer/device, you can achieve the same result by footprinting the system (not trivial) and storing that footprint in the database related to any settings it would encounter.
If those options are not available to you, then cookie will be your only remaining alternative.
An other alternative to using cookies to keep a session ID is to use cookie-less session management, which is mentioned in the article that you linked to. A cookie won't be kept on the client machine with the session identifier -- instead, it will be in the query string. It's definitely an "uglier" solution, but it's one of the few options you have. You can either keep a cookie that's sent up with each request, or stick something on the query string to identify the request.
Either way, you need some way for your server to pick up the identifier and retrieve your session data -- whether it's getting the ID from a known cookie or a known query string value.
I mean, there are probably other ways -- keeping a hidden value on each and every page, but I think that just gets even "uglier". You want to keep that information out of the page/information that you're rendering.
Similar questions have been asked before but I'm still without an answer and have spent a decent amount of time trying to find one.
The scenario is this. We have an ASP.NET MVC application which is using Forms Authentication / LINQ-to-SQL data model.
Each user can be associated with 1 or more Accounts. Upon login, the application checks how many Accounts they're associated with.
0 = Go to error page and let them know they have no access
1 = Set The User Data to use that account
2 or more = Go to a page which allows them to select which account they'd like to use (with ability to change during their visit)
How would you store this information?
Furthermore, I'd like to use this Account as the base for my controller actions. i.e. Data on subsequent pages they visit will be related to the Account they've selected.
Singleton cough comes to mind but am unsure how to implement that.
An approach which I'm currently investigating is a Base Controller that all controllers will inherit from that will
Check whether a user is logged in.
If so, check whether they have an Account Selected
No - redirect them to Account Selection page
Yes - proceed with original request
What is a recommended/best-practice way of doing this?
Thanks
Marko
Don't use a base controller. You can accomplish this using action filters. This will give you the point of intercept for checking whether they are logged on, whether there is an account selected, and even redirecting them to the error or account selection page. All you have to do is set filterContext.Result during the action filter's OnActionExecuting method to prevent the request from going through. You have complete access to session, temp data, cookies, and the whole HttpContext during the action, just as you would in the controller. Also you can property inject dependencies using a filter attribute filter provider, so that should give you any data access you need.
As far as modeling the data, I am not too familiar with Linq to SQL, but I think a normal one to many should do the trick:
User (1) <-------> (0..*) Account
public class User
{
public virtual ICollection<Account> Accounts { get; protected internal set; }
}
public class Account
{
public int UserId { get; protected internal set; }
public virtual User User { get; protected internal set; }
}
Update: Sorry, I misunderstood what you meant by "store". In MVC, there are only a few ways you can store it - Session, Cookie, and Cache (and TempData, which is just short-term session) are the most popular choices. My choice would depend. Session is probably the easiest, but if you are deployed to a server farm with a load balancer, you need to think about what would happen if the user's session jumps physical machines. Will the session remain intact?
As Jeremy says there is also cookie. No worries about load balancing here, but the semantics are a little harder to deal with than session. For example you have to send a redirect to write the cookie before you can read it, and I've never liked the fact that you have to add an expired cookie to delete one. Since this data is part of your security, you also may want to encrypt the cookie value.
If you use cache, the data will most likely still end up living in memory somewhere, like session (unless you are using a SQL session provider). Cache would probably be my last choice, since we use Azure and their cache doesn't support a lot of great MVC features. You also have the same problem with load balancers moving the user to a different machine in the cluster, where the data may have to be re-cached.
Either way, you should still use action filters for this instead of a base Controller class.
What type of scale are you talking about? Are we talking about a million users or a couple thousand?
My first thought is to create a dictionary with the key being the login username (assuming it's unique) and the value to be an array of associated accounts(key or all the data). I would then put the dictionary into cache. Expiring it whenever a new association is created.
There are a couple of problems with this approach. First, how fast are new associations being created? If they are constantly being created, then the cache is a moot point. You'd always being going to the DB. Second, if you have millions of users/associations putting all them into cache may not be practical.
Another possibility is a session state server, this would be solely dedicated to storing the relationships.
Yet another possibility is querying the database each time, depending on the size of the data set this would work. When the data set grew to a size where pulling real time data each time is not practical you could architect a solution that fits your needs.
As for persisting the selected account between requests, The options are either cookies, url or database(could be a field on the user i.e. CurrentAccount, this approach is a bit of a kludge).
Since you are using MVC I'd use the URL, with routing and a custom route constraint you could create a url that contained the account. Since the user has to login, you already know the user identity.
Example: http://www.acme.com/{account}/edit/
Checking if a user is logged in could be handled in an action filter or Application_AuthenticateRequest in the Global.asax. Authentication is fairly well implemented in ASP.NET. Heck a lot of it is driven by configuration values in the web.config.
After the authentication has been confirmed the account redirection could take place in the same method. Or you could wait and check in an action filter.