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.
Related
We are building a new ASP.Net Core WebService which will provide data from existing Database.
To reduce to load on the database and improve response times I thought about caching certain objects and configurations from the database.
I found this for caching in ASP.Net Core: https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-2.2
What seems to be the way to go. The Article also says: Do not use external input as cache keys
My Problem now is that basically all data are depending on the user or a user input.
I am aware that caching makes only sense with objects that get often used but rarely changed.
Here an simplified example when I might want to use caching: We do have holiday / workday configuration which can by per state different. So it can vary depending on the user but 100s of users might use the same configuration.
Also there are some shared components which a lot of users share but which components are returned is depending on what is requested.
So what would be the best approach to cache such entities?
I am also open for any Idea that helps me reduce the calls to the database.
Thanks and best regards,
Marc
I think you're misunderstanding. The caution is against using external user input as cache keys. In other words, you should not take some input from the user and the set something in the cache via that:
_cache.SetString(userInput, "foo");
It's not talking about setting user input as the value, i.e.:
_cache.SetString("my cache key", userInput);
It's also not talking about segregating the cache by user:
_cache.SetString($"cache key for user {userId}", "foo");
Both of the latter scenarios are fine. It's just that allowing the user to set the key itself opens yourself up to things like potential SQL injection attacks, depending on your cache store.
Also, note that it's mostly talking about unsanitized user input. If it's something like an enum where the user can pick only from a set of defined values, then you're fine. Or, if you otherwise know that the input is not going to cause issues. For example, a zip code that you've validated only contains numbers and maybe a single dash. There's nothing a malicious user can do with that, so it's fine. However, a free form text field like "Name" would be problematic to say the least.
The documentation discourages external input as cache keys, because it might lead to too many cache entries and consume quite a lot of RAM, which will in turn have negative impact on the performance.
You need to experiment. Maybe you will not end up with too many different user input variations.
You can also consider an external caching service like Memcached, where you can use additional servers as cache. This will allow you to cache many more values and reduce your load on the db.
I'm making a simple asp.net app that displays data which can be filtered based on a few different parameters. As such, the different filters that are currently selected need to be saved somewhere. I'm fairly new to .NET, and am wondering the best way to save this information. I noticed a coworker used Request.QueryString in conjunction with the Sessions dictionary. Something like this on page load:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["Category"] != null &&
Request.QueryString["Value"] != null)
{
string Category = Request.QueryString["Category"];
string CategoryValue = Request.QueryString["Value"];
// selectedFacets is the server side dictionary
selectedFacets.Add(Category, CategoryValue);
}
}
The QueryString here is changed when the user presses a button on the webpage, updating the URL.
My question is why even bother with the QueryString at all when all we're using it for is saving a value server side anyway? Wouldn't just making the button an asp controller be easier, something like:
protected void exampleCatexampleVal_Button_onClick(object sender, EventArgs e)
{
selectedFacets.Add(exampleCat, exampleVal);
}
Similar business goes on the with the Sessions dictionary: it's just used to save a bunch of values to variables on the server, so why use it in the first place? I'm sure there's a good reason, but right now they just seems overly complicated for what they do. Thank you!
Based on your code examples, I understand that you're talking about ASP.NET WebForms.
Your use case is not complete, but I'll show here some alternatives to achieve your goal. If you give further information, I'll gladly update my answer.
Before we get to it, let me just put things clear: HTTP is stateless. Understanding this basic rule is very important. It means that your server will receive a request, send it to your app (and the .NET process), get the resulting page (and assets) and send it back to the client (mostly, a browser). End of story.
(Almost) Everything that you've created to respond to the request will be lost. And that's why we have options on where to store objects/values across requests.
Server-side Session
This is one of the easiest options. You simply call this.Session.Add("key", object) and it's done. Let's dig into it:
It will use server resources. That is, the most you use the session, the most memory (and other resources, as needed) your app will consume.
It will be harder to scale, because data will be on your server memory. Vertical scale may be an option, according to your hardware, but horizontal scale will be limited. You can use a session-server or store session on a SQL Server database, but it won't be so efficient anymore.
It's attached to your client session. It will be lost if the user opens another browser or sends a link to his friend.
It's relatively safe. I say relatively because of the options below. At least it's server side.
GET arguments (AKA QueryString)
That's another option, and you know it already. You can send data back and forth using the querystring (?that=stuff&on=the&URL=youKnow).
It's limited to 2000 characters and that must be serializable. That's why you probably won't put a DataGrid there.
The user may change it. Be aware! Always sanitize data from the QueryString.
User is free to bookmark the link or send it to a friend and stuff will be the same. That's nice, mind you.
ViewState
You may have heard about it, it's the engine that makes WebForms so lovely (and so hateful). By default, each controller on your page will have its state serialized to the viewstate, which is a huge hidden field with encrypted data on your page. Go on, click "View source" and look for it. Don't scream, please. You may add arbitrary data to the ViewState just like the Session.
It's on the client side. Don't trust it.
It will be send back and forth on each request, so it will consume extra bandwidth.
It will take time to be deserialized/serialized on each request/response.
Data must be serializable (you know what I mean).
So, by now I hope that you have enough information to make your own decision.
If I missed anything, please let me know.
Have a look at this MSDN Article first. I read through it, and it may answer your question for you.
http://msdn.microsoft.com/en-us/magazine/cc300437.aspx
What you're missing, is how the asp.net page lifecycle works:
http://msdn.microsoft.com/en-us/library/ms178472(v=vs.100).aspx
The thing is, that 'server variable' won't persist between postbacks (AFAIK). It's only useful inside that page, right then. As soon as the page is disposed at the end of the cycle, that dictionary is gone. So you have to store it somewhere if you want to use it later. The article I referenced shows you all the places that you can store information to persist it and where you store it depends on how long you need it to persist, and how many users should have access to it.
Now, certainly, if you DON'T want to persist that dictionary, then sure, just store it the page variable. That's just fine. There's no reason to persist data that you never need again.
It's always good to keep in mind that there is a slight performance hit when storing and retrieving session state from database or from separate process service (StateServer). If session state is stored in-memory, you cannot scale your application to a web farm and this wastes valueable memory in the web server.
On the other hand, using query string values won't waste your memory and resources, it is fast and you don't have to think about managing session state. It gives SEO benefit and allows bookmarks/favorites.
However, you can store only limited amount of data using query string (WWW FAQs: What is the maximum length of a URL). It can also pose a security risk, if sensitive data is exposed or a malicious user tries to find a bug in your code that mishandles URL values. SQL injection attack is one scenario. What you can do is encrypt sensitive values.
Overall there are many aspects to consider here.
One of the benefits of using query string values is if you need bookmarks/favorites stored in your application that would allow a user to directly navigate to a page and have certain values be passed into the page without the assistance of an in-memory cache. Take the following for example:
I have a product page that displays a grid view of products that can be filtered by a category name. If I use the categoryId value in the query string, then I can make a bookmark to this page and then later click on the bookmark and the page will work as I left it earlier. Depending upon in-memory cache, that may or may not be there, would not guarantee that my bookmark would work every time.
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'm currently developing an application using ASP.NET MVC, and now I need to create an interface (web page) that will allow the users to pick and choose from a set of different objecs, the ones they'd like to use as the building blocks for constructing a more complex object.
My question is supposed to be generic, but to provide the actual example, let's say the application that will allow users to design pieces of furniture, like wardrobes, kitchen cabinets, etc. So, I've created C# classes representing the basic building blocks of furniture design, like basic shapes (pieces of wood that added together form a box, etc), doors, doorknobs, drawers, etc. Each of these classes have some common properties (width, height, length) and some specific properties, but all descend from a basic class called FurnitureItem, so there are ways for them to be 'connected' together, and interchanged. For instance, there are different types of doors that can be used in a wardrobe... like SimpleDoor, SlidingDoor, and so on. The user designing the furniture would have to choose wich type of Door object to apply to the current furniture. Also, there are other items, like dividing panels, shelves, drawers, etc. The resulting model of course would be a complete customized modularly designed wardrobe or kitchen cabinet, for example.
The problem is that while I can easily instantiate all the objects that I need and connect them together using C#, forming a complete furniture item, I need to provide a way for users to do it using a web interface. That means, they would probably have a toolbox or toolbar of some sort, and select (maybe drag and drop) items to a design panel, in the web interface... so, while in the browser I cannot have my C# class implementation... and if I post the selected item to the server (either a form post or using ajax), i need to reconstruct the whole collection of objects that were already previously chosen by the user, so I can fit the newly added item... and calculate it's dimensions, etc. and then finaly return the complete modified set of objects...
I'm trying to think of different ways of caching, or persisting theses objects while the user is still designing (adding and deleting items), since there may be many roundtrips to the server, because the proper calculation of dimentions (width, height, etc of contained objects) is done at the server by methods of my C# classes. It would be nice maybe to store objects for the currrent furniture being designed in a session object or cache object per user... even then I need to be able to provide some type of ID to the object being added and the one being added to, in a parent owner kind of way, so I can identify properly the object instance back in the server where the new instance will be connected to.
I know it's somehow confusing... but I hope this gives one idea of the problem I'm facing... In other words, I need to keep a set of interconnected objects in the server because they are responsible for calculations and applying some constraints, while allowing the users to manipulate each of these objects and how they are connected, adding and deleting them, through a web interface. So at the end, the whole thing can be persisted in a database. Idealy I want even to give user a visual representation or feedback, so they can see what they are designing as they go along...
Finally, the question is more so as to what approach should I take to this problem. Are C# classes enough in the server (encapsulating calculation and maybe generating each one it's own graphical representation back to the client)? Will I need to create similar classes in javascript to allow a more slick user experience? Will it be easier if I manage to keep the objects alive in a session or cache object between requests? Or should I just instantiate all objects that form the whole furniture again on each user interaction (for calculation)? In that case, I would have to post all the objects and all the already customized properties every time?
Any thoughts or ideas on how to best approach this problem are greatly appreciated...
Thanks!
From the way you've described it, here is what I'm envisioning:
It sounds like you do want a slick looking UI so yes, you'll want to divide your logic into two sets; a client-side set for building and a server-side set for validation. I would get heavy on the javascript so that the user can happily build their widget disconnected, and then validate everything once it's posted to the server.
Saving to a session opens a whole can of webfarm worms. If these widgets can be recreated in less than a minute (once they've decided what they like), I would avoid saving partials all together. If it's absolutely necessary though, I would save them to the database.
If the number of objects to construct a widget is reasonable, it could all come down at once. But if there are hundreds of types of 'doors' you're going to want to consider asynchronous calls to load them, with possible paging/sorting.
I'm confused about your last part about instantiating/posting all objects that form the whole furniture. This shouldn't be necessary. I imagine the user would do his construction on his client, and then pass up a single widget object to the server for validation.
That's what I'm thinking anyway... by the way, hello StackOverflow, this is my first post.
You might want to take a look at Backbone.js for this kind of project. It allows you to create client-side models, collections, views and controllers that would be well suited to your problem domain. It includes built in Ajax code for loading/saving those models/collections to/from the server.
As far as storing objects before the complete object is sent to the server, you could utilize localStorage, and store your object data as a JSON string.
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.