MemoryCacheEntryOptions cache is not cleared after AbsoluteExpirationRelativeToNow is expired - c#

I have sample webapp deployed to Azure. The app cached a variable using MemoryCacheEntryOptions to store a value (from database) which expire in 5 minutes.
However after 5 minutes via Chrome debugging tool, I still can query the cache, the cache value expected to be empty or whatever the new value which currently stored updated in the database.
I even tried to clear cache in the web browser, but cache seem still retain the previous value.
However when I restart the web site, and open the web app again the cache value is no longer exist.
Would any setting in Azure might affect the cache expiry?
private readonly MemoryCacheEntryOptions _cacheEntryOptions;
protected CacheService(IMemoryCache memoryCache)
{
_ memoryCache = memoryCache;
_cacheEntryOptions = new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300)
};
}

Debugging the behavior of a web application is notoriously hard, as all you got to control it is the Browser - and you never get exclusive access.
Even if you did not refresh the page, any number of things might have queried the server. The culprits start around "any search engines webcrawler" and end around "somewhat aggressive security tools" (because some viruses might use web servers). You could try a way shorter timeout. But ideally you want to have both the Server and the client you access it with run in separate virtual machines, which are only connected via the Hypervisor. That way you can be certain nobody is interfering.

Related

When listing a Drive folder's changes (via ChangeResource) for the first time, what page token should be used?

Lets say the user already has files synchronized (via my app) to their Drive folder. Now they sign into my app on a second device and is ready to sync files for the first time. Do I use the Changes API for the initial sync process?
I ask because using the Changes API requires a StartPageToken, which requires that there had been a previous sync operation. Well there is no possible way for user to already have a StartPageToken if they are synchronizing data on a device for the first time.
Google's documentation is a joke. They shouldn't leave it up to us to read between the lines and just figure this out. I'm sure I can cook up something that will "work", but how do I ever know that it is the "appropriate" and EFFICIENT way to go about handling this?
public async Task<AccessResult> GetChangesAsync(CancellationToken cancellationToken, string fields = "*")
{
ChangesResource.ListRequest listRequest = new ChangesResource.ListRequest(DriveService, startPageToken)
{
Spaces = Folder_appDataFolder,
Fields = fields + ", nextPageToken",
IncludeRemoved = true,
PageSize = 20
};
ChangeList changeList = await listRequest.ExecuteAsync(cancellationToken);
}
Here, I am looking to start syncing the user's for the first time and so a page token doesn't even make sense for that because during the first sync your goal is to get all of the users data. From then on you are looking to only sync any further changes.
One approach I thought of is to simply use ListRequest to list all of the users data and start downloading files that way. I can then simply request a start page token and store it to be used during sync attempts that occur later...
...But what if during the initial download of the user's files (800 files, for example) an error occurs, and the ListRequest fails on file 423? Because I cannot attain a StartPageToken in the middle of a ListRequest to store in case of emergency, do I have to start all over and download all 800 files again, instead of starting at file 423?
When doing changes.list for the first time you should call getStartPageToken this will return the page token you can use to get the change list. If its the first time then there will be no changes of course.
If the user is using your application from more then one device then the logical course of action would be for you to save the page token in a central location when the user started the application for the first time on the first deceive. This will enable you to use that same token on all additional devices that the user may chose to use.
This could be on your own server or even in the users app data folder on drive
I am not exactly user what your application is doing but i really dont think you should be downloading the users files unless they try to access it. There is no logical reason i can think of for your application to store a mirror image of a users drive account. Access the data they need when they need it. You shouldn't need everything. Again i dont know exactly what your application does.

SignalR - keeping updated ConnectionID

I'm writing a pretty big web system with asp.net MVC, which involves sending data in Real Time to numerous users, based on what they are subscribed to.
My team and I decided to use SignalR for that, and I am in charge of implementing it in the system.
In our case, that a user picks a group to join, and then picks 1 Thing to work on.
For that, I'm saving all the users in a DB. I'll be using the SignalR Groups to handle the first category, and when I need to push a message to a specific user (for the other thing hes picking) I'll just get his ConnectionID from the DB.
Here's the problem - every time the page is refreshed (for instance, when the user picks a group to join) he gets a new connectionID. And now he won't see anything that's pushed to him.
I saw that in the SignalR beta, and on version 2 (I only have 1.1.1 on the computer I'm working on) you can make your own IUserIdProvider (IUserIdPrefixGenerator in the beta), or IUserConnectionIdFactory etc. So I can give him the I'd I want him to have, but I don't seem to have any of those in my version of SignalR.
There are many ways to solve this, but perhaps one of the simplest ways is to associate the new connection id with the user (maybe they still have the other connection open in a different tab). This can be done using any combination of IP Address, User-Agent, Headers, or location. Another good candidate for this is either to use sessions, or just a simple identifier cookie (which is more or less what a session would do anyway).
I'll often use GUIDs for this and then create a table in the database when a new identifier cookie is created. Every time the user "refreshes" or opens a new tab, the cookie can be read in JS and sent with the hub.connect(). Then, you can create an association between the new connection id and the existing identifier cookie.
I'd highly recommend figuring out a different way to maintain your users' persisted connections. Typically, I keep all of my users connection ids stored in a concurrent dictionary to allow for thread-safe access to the collection. I remove the users from the dictionary whenever a disconnection event occurs and I add them whenever a connection event occurs.
SignalR will manage your users' connections for you. For you to do it in the database and fall out of sync with SignalR circumvents a lot of the mechanics that make it work correctly in the first place.
private readonly static Lazy<App> _instance = new Lazy<App>(
() => new App(GlobalHost.ConnectionManager.GetHubContext<AppHub>().Clients));
private readonly ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>(StringComparer.OrdinalIgnoreCase);
private IHubConnectionContext Clients { get; set; }
public App(IHubConnectionContext clients)
{
Clients = clients;
}

Losing session values

I have a process that involves a few .aspx pages. Fill out some info in one, hang on to it, move to another page that has an iframe on it, upload some documents in the iframe via a web service to a server, hang on to the list of documents and the status of the upload and then, on a third page, do something else that involves saving all the data to a database.
Before moving from page 1 to page 2, I put some data in Session variables. On page 2, the data is retrieved and displayed, some more data is put into Session variables during the process of uploading the files from within the page in the iframe on page 2 then, on page 3 the data is retrieved from Session and written to the database.
On a test server this all works perfectly. On a live server, I keep getting (random) 'object not set to a reference' errors - which seem to be reporting that the session variables have disappeared.
My understanding is that, within .aspx pages ...
HttpContext.Current.Session["myvariable"]
Session["myvariable"]
are, effectively, the same thing. I am setting my session variable just using ...
Session["Variable1"] = "fred";
Any ideas why (randomly, sometimes the process works fine on the live server) I seem to be losing my Session variables?
This is a web site as opposed to a web application. Developed in VS2010 using Framework 4.0
There can be various reasons why you are loosing the session.
Some of them are:
Your sessionState timeout has expired
You update your web.config or other file type that causes your Application Domain to recycle like files in folder App_Data
Your Application Pool gets recycled
You update your site with a lot of files just by doing copy and paste physically, and ASP.NET will automatically recycles the session.
If you are not sure of the reason you can do event logging why application pool is getting recycled. May be you will come to know about the reason and depending upon that you can take preventive measures.
For Logging you can write following code block on Application_End
public void Application_End()
{
HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null, CultureInfo.InvariantCulture);
if (runtime == null)
return;
string shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null, CultureInfo.InvariantCulture);
string shutDownStack = (string)runtime.GetType().InvokeMember("_shutDownStack", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null, CultureInfo.InvariantCulture);
//Do Logging as per your need and implementation
//Logging.Write(TraceEventType.Error, shutDownMessage, shutDownStack);
}
The is a good posiblity you save non serializable objects in you session variables and keep your session out of proc on your production server (load balancing?). Check if you objects are seriablizable and if not make them serializable.
What happens is your live server is recycling its application pools, which basically resets the memory used for applications. Normally a timeout can be set, but if the application pool recycles, this will reset your session.
The solution is to use SQL server for your session state.
Try this: http://support.microsoft.com/kb/317604
Supplemental Link: http://www.codeproject.com/Articles/104082/Configuring-ASP-session-state-on-SQL-server
If you are hosting with a larger public host, they have probably already prepped their SQL to handle session states, and you should be able to just make the change in your web.config file to use SQL session state.
Ciao
There is one more condition where sessions can lose its value.
You can use Fiddler tool to trace out this problem.
The most condition can be found when you some element like source not found in solution. At that moment server will try to reload that unfounded or lost object by restarting the project. Restarting the project will result in resetting all session objects.
Thanks.

Changing static value permanently

I have a Windows Communication Foundation (WCF) service running. When a service is called, sometimes the service has to start again and populate all the static values because I guess the webserver shuts down the service after period of inactivity. If it is called constantly, it stays active and all the values are populated. I have a static integer in that class that gets used by the service calls and I have that at 30 for example, but I sometimes set that static value using service call so that the new value is 20, but since the service gets deconstructed by the web server after a period of inactivity, the value is again initialized to 30. Is there a way to permanently set the 30 value to 20 when the WCF service gets constructed (static constructors) get called? Is there any better way to do this? I have 2-3 of these values that I want to change permanently whenever I want through a web service call.
I would suggest using the built in Settings static class
Settings.Default["StaticValue"] = "30";
Settings.Default.Save();
http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
Even without the restart, if you are only storing this value in memory it's not stored "permanently". A database or similar would be great, but if you are not using a database for anything already, using one to store a single value seems like overkill. What about writing to a file?

ASP.NET Session has expired - Event Id 1309

Some quick details:
I'm running ASP.NET 4.0.30319.0 on IIS6. I've been hosting a website that contains a ReportViewer for quite some time now (~3 years). In April, I upgraded to the 4.0 runtime, and things ran smoothly for a couple of months.
Now, I'm suddenly starting to see quite a Session Timeout exceptions occur on the pages hosting the ReportViewer. The Event Viewer has many many of these events logged, and it's rather hit or miss when it comes to actually being able to view the page. Hitting the page once, you can see the generated report. Refresh, and the error occurs. Refresh again and it returns...
I've scoured many forums trying to figure out the issue - most seem to recommend changing SQL server settings (which I'm not using), changing the AsyncRendering="False", changing the Application Pool settings, or the timeout. I'm reluctant to change any of these, as it has worked only a week ago, without this issue.
Short of a Windows Update, or someone making a change to the server without my knowledge, I'm out of ideas...
Update
I've tried increasing the maximum virtual memory, in the app pool, which didn't work.
I have almost the same problem, after upgrading to .NET 4.0 and Report Viewer 2010. I did both upgrades at the same time, now I'm not sure who's to blame. In my case, refresh does work, but the users keep the page open during the night, then click on refresh the next morning, when the session is already lost. Our app pool recycles every night.
I believe the report viewer is supposed to keep the session alive, but it doesn't. There's no request of any kind from the report viewer. It then loses it's stored state when the session ends, either by session expiration or app recycling. I'm also using InProc, I tried to change it, but the report viewer did not work with State Server. I will try again at a later time, to move away from InProc.
See my similar question.
I haven't put it into production yet, but I gave the aspx pages with the reports a custom page to derive from, and I will check there if the session has actually timed out. It basically reloads the report page, instead of doing postback where it expects the session.
if (Context.Session != null)
{
//Tested and the IsNewSession is more advanced then simply checking if
// a cookie is present, it does take into account a session timeout, because
// I tested a timeout and it did show as a new session
if (Session.IsNewSession)
{
// If it says it is a new session, but an existing cookie exists, then it must
// have timed out (can't use the cookie collection because even on first
// request it already contains the cookie (request and response
// seem to share the collection)
string cookieHeader = Request.Headers["Cookie"];
if ((null != cookieHeader) && (cookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
{
Response.Redirect(Request.Url.ToString());
}
}
}

Categories