I'm working on a project which I need to build a list of menus according with the profile of the logged user. But, currently I have to build this list each time the page is loaded and this is not too good for my project.
What I want to do is get this list only when the user logs in and use it each time that I need it. My idea is store this list in the Session when the user logs in. But I know the session isn't a good practice.
I've tried to use the session, cookie and OutputCache in ActionResult but only the session works.
Is there a way to store my list in a "global variable", or something like that, and use it always I need it?
I can suggest two options for you problem.
Use Session object for each user.
or
Use Caching mechanism - If you have implemented some caching mechanism in you application, you can create one object per one user storing the navigation menu(Something like Redis, AppFabric or .NET caching).
Object related to the menu should be create only one time for the user(You can create it during the login).
I would create a database storing the built list when profiles are created/changed (could be something as simple as a JSON string?) referenced by the user id.
Simply then a case of selecting this with a single user id value - a simple data type can get a complex datatype.
Thanks for all help.
To solve my issue, I had to use the Session. Why? Because each user has his own '(SidebarViewModel)Session["sidebar"]' which contains all specific menus, name, ids and avatar.
I've tried to use the "OutputCache" (My own attribute class), but as my menu is a ChildAction I couldn't clear my cache on logoff and it's not so good to the user who can change his own avatar when he wants to. I also tried to use the Application but it was almost the same case of the Sessions.
PS: I don't like the Sessions, but I think it's the best way for now.
Related
I'm currently working on a web application that has a lot of user settings.
Things that can be displayed, graphics, statistics, coloring etc.
For example a setting would be something like (ItemID = 1, MyCutOff = $5.00, AlertColor=Red)
There are a lot of these different types of settings some more complicated than others.
Right now what I'm doing is on Login the users settings are read and stored in a DataTable which is stored in session, but I'm sure that is not best practice.
What is the best practice to deal with this ? I'd like to be as efficient as possible since the application has the possibility of having many concurrent users.
Thanks.
If you use database to hold your session, then you read them from one table and you move them to some other table.
For me you can left them on the DataTable that you already have them and just ask for them when you need them.
Now one optimization that you can do in a page cycle is to use the HttpContext.Current.Items[], for example if you load a parameter from your table and you need to use it on 20 different place in a page call (eg, inside custom controls, inside the master page, inside the page etc) you can use the HttpContext.Current.Items[] to store it.
There are also the asp.net profile properties that can be customized and used for your users.
If they are truly just settings ( things that determine the UI etc) you could also use localStorage. Really easy to stringify and parse json data in key value pairs using localStorage. As long as its not sensitive data. If you need to pass the params back server side this may not always be the best option but that's for you to decide as you know the project but may be worth a look.
I have a need to share information from Web Parts on one page, with Web Parts on a second page. SharePoint does not have a default Session State, and let's say for arguments sake I cannot enable Session.
If there is a LOT of information, more than can be sent via Query String, is there another option?
Depending on the nature of the data that needs to be passed along, there are different ways to go about it. My first idea would probably be to save it in cookies on the active user. Another alternative is to save data to the property bag of the SPUser-object of the current user.
Really feels like a scenario to user Session-state though.. :)
I have a page which has 3 user controls. I want some data from database to be shared between these user controls. Where actually i should save it. I am using a static class to store it now. I dont think this is a good idea.
these data actually depends upon the first usercontrol. So if the user has made any changes to the first usercontrol's controls than i am fetching these data again from the database.
I am not sure where should i store this data. Should I use session or a static class?
One way would be to store it in a Session variable and read/write that Session variable via a property defined in a base class that all 3 of your controls inherit from (or, as you said, a static class they all have access to).
Check out this answer for an example of how I would define a property that does read/write on a Session variable.
If it's data that you want to share for a longer time, then saving it into the database and calling it from relevant pages is good. Especially if they may decide to leave/quit before getting to the last page that would otherwise save it.
If you are just saving it between pages, and after that it doesn't need to be kept, using the Session is certainly valid.
This 2 options don't have the same scope.
Session keep data for a user as the user navigates ASP.NET pages in a Web application.
and
Static class keep data for all the live of your Web Application (any users, any sessions)
ASP.NET provides different state management approaches depending on your requirements.
Static class is a bad idea because all your visitors will see the same data.
You can get additional information about states here at pick one that is best for your task.
Your options are:
Viewstate [scope is the page, data
survives post-back]
Session [scope is
the client session, data survives
across pages]
Applicationstate
[for global scope]
Database and a combination
of the above [scope is across client
sessions]
Static classes are not a good idea, for reasons already mentioned.
See Maintain state of an asp.net page
I'm building a web system and various clients will have alternate text for default instances throughout the site. One place is the main nav but there are others. The default may be "project" but they may want to call it "event".
I'm heading down the road of calling all the terminology settings (there's a list of about 15) and creating an ArrayList that has the id and either the default or their replacement as the items in the ArrayList.
I've also got a enum key list called TermKey that has the defaults and the corresponding ID number.
Throughout the code I'll reference TermKey.Project and then do one of these things that I see as options.
1-pull the text from the session (if the client has set it to "event" then the text "event" will be waiting for the call there)
2-pull the text from the database every time I need it.
3-pull the client's list each time a page loads.
Some thoughts on the impact each way or if there is a best practice for this sort of thing would be appreciated.
The session isn't the best place for this kind of information. While yes, it is user-bound, the session state is really a repository for user-bound, session-bound information. What you seem to have is information that really has a scope beyond session.
The best way to reflect this information is to use a custom ASP.NET Profile Provider. You would use it to expose properties for the information you need to expose, while the logic in the properties would handle setting the values to the appropriate values based on the user in your system (or, an anonymous user, if they are not authenticated).
In your case, you could cache the values and access the database as needed in the profile provider.
Then, this information is exposed through the Profile property on the HttpContext class (and through the Profile property on the HttpProfileBase class as well if you are using ASP.NET MVC).
Anyway you shouldn't call DB on every page just to get alternate text. I think it is fine to store them in session if there are not too many of them (per user)
The way I've done this in the past is to have a database type code table and then a client-specific translation table like this:
TABLE ObjectType
ObjectTypeCode
TABLE ClientObjectTypeTranslation
ClientId
ObjectTypeCode
OverrideDescription
This allows my code to always reference what I know (i.e. ObjectTypeCode) and I then join to the translation table on every query and display the override description where relevant.
Though, this may be overkill for your scenario.
Session is ok to do this if you want to persist across sessions (and it's not TOO much data). Another option would be cookies.
I'd recommend on session start, instantiate session vars in a User object property, then can reference, User.DefaultText
If this is specific to each user, you might as well use session. Don't overuse is (and only use it for small amounts of data).
Going to the database for each request can be overkill, especially if this data doesn't change often - it will be much faster to retrieve from local memory than from over the network.
Having said that, using session InProc will limit you to a single server and will not allow you to scale to a web farm.
I have a multi-user ASP.NET MVC application. The users are not supposed to see or do anything with each other's data.
One of my controller actions is the obligatory POST to /Edit to edit a record (e.g. a contact). Now here is my problem: What if somebody forges a simple POST to /Edit (which automatically model-binds to my contact class) and edits somebody else's information? As each record is identified by Id, all that would have to be done is make a fake POST with Id XXX and then record # XXX would be overwritten with whatever the attacker supplied. How can I stop this?
The only thing I thought of is fetching the original instance every time first from the DB, check that it is in fact within the user's scope of editable objects (the ones he'd usually see to edit) and only if that check passes to proceed with UpdateModel and committing the update changes.
Is there a better way?
Edit: This is not a Cross Site/CSRF attack. Another logged in user can do this.
Authorization for the view/page and authorization for the particular object are really two separate concepts. The best approach is problem to use an Authorize attribute in conjunction with the ASP.NET roles system to either grant or deny access to a given page. Once you have verified that the user has access to the page, then you can verify whether he has the permission he is requesting for the object on which he is requesting it. I use this approach in my application, and it works great. By using the Authorize filter first, it significantly improves performance since the actual object permission checking is a much heavier operation.
Also, I use a home brewed rules system to actually set and determine whether the user has access to the object. For example, in my system, administrators have full access to every object. (That's a rule.) The user who creates the objects has full access to the object (also specified by a rule). Additionally, a user's manager has full access to every thing his employees have access to (again specified by a rule.) My application then evaluates the object to see if any of the rules apply--starting with the lest complex rules first and then moving on to the more complex rules last. If any rule is positive, I discontinue rule evaluation and exit the function.
What you could do is exclude the ID in the model binding with this syntax:
public ActionResult Edit([Bind(Exclude="Id")] User userToEdit)
and then fetch the ID from the current logged in user instead, so that it is only the logged in user that can edit his own items and noone elses.
Loading the original record first and checking the owner sounds like a good approach to me. Alternatively you could add a hidden field containing the record ID and cryptrographically sign that field to make sure it can't be changed, or take the record ID, hash it using the user ID as a salt and check that (assuming you're using the membership providers you should use the provider unique ID, not the login name)
This question reminded me of an article that covers a similar issue (in light of URL manipulation attacks) that i had bookmarked. They deal with an authenticated user messing with the data of another user. You might find it useful:
link text
Edit: This link should be correct:
Prevent URL manipulation attacks