ASP.net 4.0 Fragment Caching using Custom Cache Provider generated key - asp.net

I have implemented a disk based Custom Cache Provider which works fine except from one problem. When i use the provider in aspx Pages the generated key is of the from "a2/../../default.aspx" which is fine. When I use the same provider in User Controls the generated key is of the form "lfffffff40e80...." and this is fine till the application pool recycles. Then for the same user control a similar key is generated (but not the same) meaning that the cashed user control cannot be accessed with the new key and a new entry is generated in the Disk Cache for the same user control.
Is this the way Custom Cache Providers work with User Controls? How can I generate the same key for the User Control when the application pool recycles?
Thank you in advance!

I don't believe that there is a way to control how cache keys are created - for a user control, its an involved process that included combining multiple hash codes and/or including stack trace hash etc. Because invariably, hash code of some factory object is used in the computation of cache key, you will get a different key in fresh app-domain (after app pool recycle) because hash code of object would differ.
As such I don't see any major issue even if new cached copy is created after app pool recycle - because you need to tune that time as well as (you cannot have tow frequent app pool recycles because application start code will need to be run after each recycle).
BTW, you can have a Shared copy of cache for multiple instances of user controls on different pages.

Related

Disadvantage of using session[""] in asp.net

In my project I use session to store user information ( username, password, personal image, and gender ) to be used in all pages of my project. I also use two other session to store small strings. Is there any disadvantage of using session ? also is there any risk of using session to store user password ?
Some things to take into account:
Don't store passwords. You should hash the incoming password, validate against the hash in your DB, and not hold on to it afterwards.
You should try to avoid using a write-access Session throughout the application, since you'll end up forcing asp.net to serialize incoming requests from the same session. Use read-only Session to avoid that. This could become apparent if you initiate multiple ajax calls simultaneously. More info here: https://connect.microsoft.com/VisualStudio/feedback/details/610820/session-based-asp-net-requests-are-serialized-and-processed-in-a-seemingly-inverse-order
Storing too much data in the Session could cause scalability issues, since all that information is held in memory on the server. If you switch over to SQL storage for sessions (common in webfarm/cloud deployments), then if the session is large every request on the server will have that Session data going back and forth between the server and the DB.
Content that goes into the session should be Serializable, just in case you decide to move over to a different persistent storage (such as sql server)
Using Sessions to retain information may not go well with stateless REST/WebApi endpoints (if you need to create any in the future)
Excessive use of Session for storage could make unit testing slightly more difficult (you will have to mock the Session)
By "personal image" I assume you are storing a url or such, and not an actual binary image. Avoid storing binary content. Only return the binary image file when the browser requests it, and don't store it in memory, the browser can cache that content easily.
You might also find the references linked in this answer to be useful in providing additional information: https://stackoverflow.com/a/15878291/1373170
The main problem with using Session and any machine depending properties is the scalability of the web site, so if you wanted to deploy your web site to a farm of servers then you can see the problem with depending on a machine state property since the request may be processed on different machines.
Hope that helps.

Setting Global Variables within an ASP.NET Web Project on Login and set Expiry Time

I'm developing a revised version of a system I have been using for years, but with all the advantages of .NET features that were not around when I first made this.
It's proving a steep learning curve!
So, when a user logs in through my Login.aspx page which simply compares username/password to Database record, the system creates a session variable containing the user's Username and various other things.
There are two type of variable which will be common to all elements of this system
User Specific data, Username, Permissions, etc
Setting variables, drawn from a database of pre-set facilities which are setup within the system, some will determine which facilities work, how they work, and some will be dependant upon the User's permission.
Obviously, I could set everything within the Session data, but that'd be inefficient wouldn't it?
If I were to set these globally available variables in my App_Code, how would I go about setting this up so that, for example, those variables which require a database call, are set for the duration of the Logged-In session and do not require constant Database lookups?
Further to that, those variables which are dependant on the session state, would need clearing on each LogOut.
I am using VB.NET.
Using global variables is not a good idea most of the time. In webapps, global variables are even worse because the intrinsic mulituser nature of web applications.
You have to maintain a set of vars for every single user - and thats excactly what session state is built for!
So why bothering using session state? After all its (by default) just some in memory collection of data magically bound to a single users session by the ASP.NET framework for you.
Further to that, those variables which are dependant on the session state, would need
clearing on each LogOut.
Even that can be done with Session.Abandon() in a single line when using session state.
When caching data that is not user dependant, it would be better to use the ASP.NET Cache as Tim suggested.

enterprise library caching - remove objects from outside process (console app)

We are thinking about using the enterprise library caching framework in our asp.net 3.5 application to store small datatables of our most hit products.
Is there a way to write an outside process, like a console application, to remove these datatables, if needed? For example, a client can come in and update the data for a product, which will make the datatable stored in cache out of date. When this happens, I would like an outside application go into the cache and remove or even update the cache with the new data.
I can think of two approaches to remove cache items from out of process.
The first is to use a FileDependency when adding items to your cache. When you want to expire a cache item then modify the file.
DataTable books = GetTopBooks();
ICacheManager cacheManager = CacheFactory.GetCacheManager();
cacheManager.Add("books", books, CacheItemPriority.NotRemovable, new BookCacheRefreshAction(),
new FileDependency("books.xml"));
Then an external process can expire your DataTable by modifying the appropriate file on disk (in this case books.xml). You can also configure an ICacheItemRefreshAction to refresh the cache (e.g. from the database) when it is expired.
If for some reason the file based approach is not sufficient then the second approach would be to create a custom interface that could be invoked by the out of process application. e.g. create a web service which will remove items from the cache and potentially refresh the cache item.

Caching the profiles from SqlProfileProvider -- ProfileManager.GetAllProfiles result

I'm using the SqlProfileProvider on one of my websites and in one page I need to fetch the whole list of profiles (it is an intranet).
The method that I use is the ProfileManager.GetAllProfiles(). The problem is that its performance is really bad and it slows down the website considerably.
Therefore, I was thinking of caching the result of the method call in the Application scope as a DataTable (so I could filter/search on it as well).
My problem is that I have several servers running this webapp, and I would like the cache to be in sync. I started using memcached but I was put off by some problems (hence going back to thinking in caching in the Application scope).
So, here are my questions:
Would it be efficient to store the DataTable containing the profiles in the Application object? Or, is it possible to store objects in the Cache and have them available for all clients/browsers?
Is it possible to add a (SQL) Cache Depedency to this cache?
You could cache portions of the web page which will depend on the list of profiles by putting them in a user control and marking it as cacheable. SqlCacheDependency cache policy expiration could be defined as well. As for the cache location, every web server in the farm will have it's own version in memory but using cache expiration will make sure that this version is not out of sync with the data in the DB.
Page or fragment caching is the most effective caching technique because contrary to caching your model (a DataTable or whatever) you don't pay the price of HTML rendering.

Can you share the session variables between two .net 2.0+ applications?

I was told this works, but...
I guess I'm just not getting this, it seems there's a hidden step I may be missing, can anyone correct this or point out my mistake? Thanks.
I have a blank solution:
- inside is two .net 2.0 web applications
1) webapp1
2) webapp2
I want them to share the same session data.
My page setups:
Application 1:
Session("value") = "this is the value"
Application 2:
If Not (Session("value") Is Nothing) Then
value = Session("value").ToString()
End If
My thought process:
1) go to services, turn on the asp.net state service
2) open the web configs in both projects: set the
< machineKey
validationKey="BFE2909A81903BB303D738555FEBC0C63EB39636F6FEFBF8005936CBF5FEB88CE327BDBD56AD70749F502FF9D5DECF575C13FA2D17CA8870ED21AD935635D4CC"
decryptionKey="2A86BF77049EBA3A2FA786325592D640D5ACD17AF8FFAC04" validation="SHA1" />
< sessionState mode="StateServer" stateConnectionString="tcpip=localhost:42424"
cookieless="false" timeout="20"/>
in both sites.
3) compile and test the site
4) become disappointed because it does not work. I never see the session from the second webapp.
You cannot share sessions between different ASP.NET applications without some custom code. What you did in web.config was to use an out of process sessions, which means that data will no longer reside into memory but into the memory of a dedicated machine. This is useful for server farms and it uses the ApplicationName to know which application the session belongs to. So basically your applications need to have the same name if you want them to share sessions. There are some dirty workarounds though.
Why do you want to share Sessions between applications? ASP.NET Session is not designed to do that.
Your proposed solution of using the same ASP.NET State Server does not work because your user will simply get 2 different session tokens, even if they use your 2 applications concurrently from the same machine, and same browser. You need to consider how Session works to understand why this is.
From MSDN:
ASP.NET session state enables you to store and retrieve values for a
user as the user navigates ASP.NET pages in a Web application. HTTP is
a stateless protocol. This means that a Web server treats each HTTP
request for a page as an independent request. The server retains no
knowledge of variable values that were used during previous requests.
ASP.NET session state identifies requests from the same browser during
a limited time window as a session, and provides a way to persist
variable values for the duration of that session.
ASP.NET Session is a metaphor for a user's current interaction with one ASP.NET application. It exists in ASP.NET to give us a place to store temporary state data between the various page requests that a user makes while using your application.
If your applications are very closely related, e.g. the user uses both at the same time, or almost the same time, you could consider merging them into a single ASP.NET application. You could deploy them into different Virtual Directories to maintain some degree of logical separation, but use only one Application in IIS.
If your applications are not that closely related, perhaps they should be sharing the same database as a means to exchange data, or using an API e.g. based on Web Services to exchange information.
They will share session data if they are in the same app pool and the session mode is set to inproc. The way that stateserver and sqlstate work is they use the root of your web address as logical boundaries.
Eg if they are both hosted on the same address and port (or 'site' in iis) but in different sibfolders then they should share session I think.
Additionally both apps must run on the same domain so that user browser use one cookie to store session id.

Resources